├── .gitignore ├── scripts ├── build_docker_image.sh ├── Dockerfile.build ├── build.sh ├── build_on_docker.sh ├── run_on_docker.sh └── run_on_docker_daemon.sh ├── docs └── images │ ├── logo.png │ ├── logo-mini.png │ └── run-on-arukas.png ├── vendor ├── github.com │ ├── sacloud │ │ └── libsacloud │ │ │ ├── sacloud │ │ │ ├── doc.go │ │ │ ├── member.go │ │ │ ├── region.go │ │ │ ├── delete_cache_result.go │ │ │ ├── product_internet.go │ │ │ ├── ipaddress.go │ │ │ ├── account.go │ │ │ ├── ssh_key.go │ │ │ ├── product_server.go │ │ │ ├── license.go │ │ │ ├── product_license.go │ │ │ ├── ostype │ │ │ │ └── archive_ostype.go │ │ │ ├── ftp_server.go │ │ │ ├── ipv6addr.go │ │ │ ├── icon.go │ │ │ ├── note.go │ │ │ ├── product_disk.go │ │ │ ├── cdrom.go │ │ │ ├── zone.go │ │ │ ├── public_price.go │ │ │ ├── internet.go │ │ │ ├── subnet.go │ │ │ ├── ipv6net.go │ │ │ ├── bridge.go │ │ │ ├── interface.go │ │ │ ├── bill.go │ │ │ ├── archive.go │ │ │ ├── instance.go │ │ │ ├── appliance.go │ │ │ ├── auth_status.go │ │ │ ├── switch.go │ │ │ ├── auto_backup.go │ │ │ ├── vpc_router.go │ │ │ └── server.go │ │ │ ├── libsacloud.go │ │ │ ├── api │ │ │ ├── bridge.go │ │ │ ├── note.go │ │ │ ├── region.go │ │ │ ├── ssh_key.go │ │ │ ├── subnet.go │ │ │ ├── license.go │ │ │ ├── zone.go │ │ │ ├── ipv6net.go │ │ │ ├── public_price.go │ │ │ ├── product_disk.go │ │ │ ├── packet_filter.go │ │ │ ├── product_license.go │ │ │ ├── product_internet.go │ │ │ ├── icon.go │ │ │ ├── auth_status.go │ │ │ ├── webaccel.go │ │ │ ├── ipaddress.go │ │ │ ├── switch.go │ │ │ ├── product_server.go │ │ │ ├── cdrom.go │ │ │ ├── ipv6addr.go │ │ │ ├── interface.go │ │ │ ├── internet.go │ │ │ ├── auto_backup.go │ │ │ └── simple_monitor.go │ │ │ ├── Dockerfile │ │ │ ├── docker-compose.yml │ │ │ └── Makefile │ ├── stretchr │ │ └── testify │ │ │ ├── assert │ │ │ ├── assertion_forward.go.tmpl │ │ │ ├── errors.go │ │ │ ├── forward_assertions.go │ │ │ ├── doc.go │ │ │ └── http_assertions.go │ │ │ └── LICENSE │ ├── mackerelio │ │ └── mackerel-client-go │ │ │ ├── Makefile │ │ │ ├── org.go │ │ │ ├── graph_defs.go │ │ │ ├── alerts.go │ │ │ ├── README.md │ │ │ ├── dashboards.go │ │ │ └── mackerel.go │ ├── davecgh │ │ └── go-spew │ │ │ ├── LICENSE │ │ │ └── spew │ │ │ └── bypasssafe.go │ └── pmezard │ │ └── go-difflib │ │ └── LICENSE ├── gopkg.in │ └── urfave │ │ └── cli.v2 │ │ ├── cli.go │ │ ├── GNUmakefile │ │ ├── appveyor.yml │ │ ├── LICENSE │ │ ├── funcs.go │ │ ├── args.go │ │ ├── category.go │ │ ├── flag-types.json │ │ └── errors.go └── vendor.json ├── version └── version.go ├── Dockerfile ├── job ├── worker │ ├── timer │ │ ├── reconcile_hosts.go │ │ └── detect_resource.go │ ├── mackerel │ │ ├── mackerel_test.go │ │ ├── post_metrics.go │ │ ├── regist_target.go │ │ ├── find_target.go │ │ ├── reconcile_by_mac_address.go │ │ ├── regist_graph_defs.go │ │ └── functions.go │ ├── sacloud │ │ ├── detect_router.go │ │ ├── add_agent_tag.go │ │ ├── detect_server.go │ │ ├── functions.go │ │ ├── detect_database.go │ │ ├── detect_vpcrouter.go │ │ ├── detect_loadbalancer.go │ │ ├── sacloud_test.go │ │ ├── collect_router_metrics.go │ │ ├── collect_loadbalancer_metrics.go │ │ ├── collect_vpcrouter_metrics.go │ │ ├── collect_server_metrics.go │ │ └── collect_database_metrics.go │ └── exchange │ │ ├── exchange_base_test.go │ │ ├── exchange_loadbalancer_test.go │ │ ├── exchange_server_test.go │ │ ├── exchange_router_test.go │ │ ├── exchange_server.go │ │ ├── exchange_database.go │ │ ├── exchange_loadbalancer.go │ │ ├── exchange_database_test.go │ │ ├── exchange_vpcrouter.go │ │ ├── exchange_vpcrouter_test.go │ │ └── exchange_router.go ├── core │ ├── job_request.go │ ├── timer_job.go │ ├── option_test.go │ ├── job.go │ ├── payload_types.go │ └── queue.go ├── runner.go ├── health_check_server.go ├── router.go └── dispatcher.go └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | .env 3 | -------------------------------------------------------------------------------- /scripts/build_docker_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker build -t sackerel:latest . -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sacloud-archives/sackerel/HEAD/docs/images/logo.png -------------------------------------------------------------------------------- /docs/images/logo-mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sacloud-archives/sackerel/HEAD/docs/images/logo-mini.png -------------------------------------------------------------------------------- /docs/images/run-on-arukas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sacloud-archives/sackerel/HEAD/docs/images/run-on-arukas.png -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/doc.go: -------------------------------------------------------------------------------- 1 | // Package sacloud is define models for SakuraCloud. 2 | // 3 | package sacloud 4 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/libsacloud.go: -------------------------------------------------------------------------------- 1 | // Package libsacloud is the SAKURA CLOUD API v1.1 Client for Go. 2 | package libsacloud 3 | 4 | // Version バージョン 5 | const Version = "1.0.0-rc2" 6 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentWithoutT "a"}} 2 | func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { 3 | return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) 4 | } 5 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/member.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // Member 会員情報 4 | type Member struct { 5 | // Class クラス 6 | Class string `json:",omitempty"` 7 | // Code 会員コード 8 | Code string `json:",omitempty"` 9 | // Errors [unknown type] `json:",omitempty"` 10 | } 11 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/region.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // Region リージョン 4 | type Region struct { 5 | *Resource 6 | // Name 名称 7 | Name string `json:",omitempty"` 8 | // Description 説明 9 | Description string `json:",omitempty"` 10 | // NameServers ネームサーバー 11 | NameServers []string `json:",omitempty"` 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/delete_cache_result.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // DeleteCacheResult ウェブアクセラレータ キャッシュ削除APIレスポンス 4 | type DeleteCacheResult struct { 5 | // URL URL 6 | URL string `json:",omitempty"` 7 | // Status ステータス 8 | Status int `json:",omitempty"` 9 | // Result 結果 10 | Result string `json:",omitempty"` 11 | } 12 | -------------------------------------------------------------------------------- /scripts/Dockerfile.build: -------------------------------------------------------------------------------- 1 | FROM golang:1.7.1-alpine 2 | MAINTAINER Kazumichi Yamamoto 3 | 4 | RUN set -x && apk add --no-cache --virtual .build_deps bash git make zip 5 | RUN go get -u github.com/kardianos/govendor 6 | 7 | ADD . /go/src/github.com/sacloud/sackerel 8 | 9 | WORKDIR /go/src/github.com/sacloud/sackerel 10 | CMD ["make"] 11 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import "fmt" 4 | 5 | var ( 6 | // Version app version 7 | Version = "0.0.3" 8 | // Revision git commit short commithash 9 | Revision = "xxxxxx" // set on build 10 | ) 11 | 12 | // FullVersion return sackerel full version text 13 | func FullVersion() string { 14 | return fmt.Sprintf("%s, build %s", Version, Revision) 15 | } 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.7.1-alpine 2 | LABEL maintainer="Kazumichi Yamamoto " 3 | 4 | RUN set -x && apk add --no-cache --virtual .build_deps bash git make zip 5 | RUN go get -u github.com/kardianos/govendor 6 | 7 | ADD . /go/src/github.com/sacloud/sackerel 8 | WORKDIR /go/src/github.com/sacloud/sackerel 9 | RUN make build 10 | 11 | ENTRYPOINT ["bin/sackerel"] 12 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/product_internet.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // ProductInternet ルータープラン 4 | type ProductInternet struct { 5 | *Resource 6 | // Name 名称 7 | Name string `json:",omitempty"` 8 | // BandWidthMbps 帯域幅 9 | BandWidthMbps int `json:",omitempty"` 10 | // ServiceClass サービスクラス 11 | ServiceClass string `json:",omitempty"` 12 | *EAvailability 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/bridge.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // BridgeAPI ブリッジAPI 4 | type BridgeAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewBridgeAPI ブリッジAPI作成 9 | func NewBridgeAPI(client *Client) *BridgeAPI { 10 | return &BridgeAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "bridge" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/note.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // NoteAPI スタートアップスクリプトAPI 4 | type NoteAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewNoteAPI スタートアップスクリプトAPI作成 9 | func NewNoteAPI(client *Client) *NoteAPI { 10 | return &NoteAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "note" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/region.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // RegionAPI リージョンAPI 4 | type RegionAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewRegionAPI リージョンAPI作成 9 | func NewRegionAPI(client *Client) *RegionAPI { 10 | return &RegionAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "region" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/ssh_key.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // SSHKeyAPI 公開鍵API 4 | type SSHKeyAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewSSHKeyAPI 公開鍵API作成 9 | func NewSSHKeyAPI(client *Client) *SSHKeyAPI { 10 | return &SSHKeyAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "sshkey" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/subnet.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // SubnetAPI サブネットAPI 4 | type SubnetAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewSubnetAPI サブネットAPI作成 9 | func NewSubnetAPI(client *Client) *SubnetAPI { 10 | return &SubnetAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "subnet" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/license.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // LicenseAPI ライセンスAPI 4 | type LicenseAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewLicenseAPI ライセンスAPI作成 9 | func NewLicenseAPI(client *Client) *LicenseAPI { 10 | return &LicenseAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "license" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/zone.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // ZoneAPI ゾーンAPI 4 | type ZoneAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewZoneAPI ゾーンAPI作成 9 | func NewZoneAPI(client *Client) *ZoneAPI { 10 | return &ZoneAPI{ 11 | &baseAPI{ 12 | client: client, 13 | // FuncGetResourceURL 14 | FuncGetResourceURL: func() string { 15 | return "zone" 16 | }, 17 | }, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/errors.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // AnError is an error instance useful for testing. If the code does not care 8 | // about error specifics, and only needs to return the error for example, this 9 | // error should be used to make the test code more readable. 10 | var AnError = errors.New("assert.AnError general error for testing") 11 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/ipv6net.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // IPv6NetAPI IPv6ネットワークAPI 4 | type IPv6NetAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewIPv6NetAPI IPv6ネットワークAPI作成 9 | func NewIPv6NetAPI(client *Client) *IPv6NetAPI { 10 | return &IPv6NetAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "ipv6net" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/ipaddress.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // IPAddress IPアドレス(IPv4) 4 | type IPAddress struct { 5 | // HostName ホスト名 6 | HostName string `json:",omitempty"` 7 | // IPAddress IPv4アドレス 8 | IPAddress string `json:",omitempty"` 9 | // Interface インターフェース 10 | Interface *Internet `json:",omitempty"` 11 | // Subnet IPv4サブネット 12 | Subnet *Subnet `json:",omitempty"` 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/account.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // Account さくらのクラウド アカウント 4 | type Account struct { 5 | // *Resource //HACK 現状ではAPI戻り値が文字列なためパースエラーになる 6 | 7 | // ID リソースID 8 | ID string `json:",omitempty"` 9 | // Class リソースクラス 10 | Class string `json:",omitempty"` 11 | // Code アカウントコード 12 | Code string `json:",omitempty"` 13 | // Name アカウント名称 14 | Name string `json:",omitempty"` 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/public_price.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // PublicPriceAPI 料金情報API 4 | type PublicPriceAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewPublicPriceAPI 料金情報API 9 | func NewPublicPriceAPI(client *Client) *PublicPriceAPI { 10 | return &PublicPriceAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "public/price" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/product_disk.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // ProductDiskAPI ディスクプランAPI 4 | type ProductDiskAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewProductDiskAPI ディスクプランAPI作成 9 | func NewProductDiskAPI(client *Client) *ProductDiskAPI { 10 | return &ProductDiskAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "product/disk" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/packet_filter.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // PacketFilterAPI パケットフィルターAPI 4 | type PacketFilterAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewPacketFilterAPI パケットフィルターAPI作成 9 | func NewPacketFilterAPI(client *Client) *PacketFilterAPI { 10 | return &PacketFilterAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "packetfilter" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/product_license.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // ProductLicenseAPI ライセンスプランAPI 4 | type ProductLicenseAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewProductLicenseAPI ライセンスプランAPI作成 9 | func NewProductLicenseAPI(client *Client) *ProductLicenseAPI { 10 | return &ProductLicenseAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "product/license" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/product_internet.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // ProductInternetAPI ルータープランAPI 4 | type ProductInternetAPI struct { 5 | *baseAPI 6 | } 7 | 8 | // NewProductInternetAPI ルータープランAPI作成 9 | func NewProductInternetAPI(client *Client) *ProductInternetAPI { 10 | return &ProductInternetAPI{ 11 | &baseAPI{ 12 | client: client, 13 | FuncGetResourceURL: func() string { 14 | return "product/internet" 15 | }, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /job/worker/timer/reconcile_hosts.go: -------------------------------------------------------------------------------- 1 | package timer 2 | 3 | import ( 4 | "github.com/sacloud/sackerel/job/core" 5 | "time" 6 | ) 7 | 8 | // ReconcileHostTimerJob タイマー起動でのホストリコンサイルジョブ 9 | func ReconcileHostTimerJob(timerDuration time.Duration) *core.TimerJob { 10 | return core.NewTimerJob("ReconsileAll", reconsileAll, timerDuration) 11 | } 12 | 13 | func reconsileAll(queue *core.Queue, option *core.Option, job core.JobAPI) { 14 | queue.PushRequest("reconcile-all", nil) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/ssh_key.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // SSHKey 公開鍵 6 | type SSHKey struct { 7 | *Resource 8 | // Name 名称 9 | Name string `json:",omitempty"` 10 | // Description 説明 11 | Description string `json:",omitempty"` 12 | // PublicKey 公開鍵 13 | PublicKey string `json:",omitempty"` 14 | // Fingerprint フィンガープリント 15 | Fingerprint string `json:",omitempty"` 16 | // CreatedAt 作成日時 17 | CreatedAt *time.Time `json:",omitempty"` 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/forward_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | // Assertions provides assertion methods around the 4 | // TestingT interface. 5 | type Assertions struct { 6 | t TestingT 7 | } 8 | 9 | // New makes a new Assertions object for the specified TestingT. 10 | func New(t TestingT) *Assertions { 11 | return &Assertions{ 12 | t: t, 13 | } 14 | } 15 | 16 | //go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl 17 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/product_server.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // ProductServer サーバープラン 4 | type ProductServer struct { 5 | *Resource 6 | // Name 名称 7 | Name string `json:",omitempty"` 8 | // Description 説明 9 | Description string `json:",omitempty"` 10 | // CPU CPUコア数 11 | CPU int `json:",omitempty"` 12 | // MemoryMB メモリ(MB単位) 13 | MemoryMB int `json:",omitempty"` 14 | // ServiceClass サービスクラス 15 | ServiceClass string `json:",omitempty"` 16 | *EAvailability 17 | } 18 | -------------------------------------------------------------------------------- /job/worker/timer/detect_resource.go: -------------------------------------------------------------------------------- 1 | package timer 2 | 3 | import ( 4 | "github.com/sacloud/sackerel/job/core" 5 | "time" 6 | ) 7 | 8 | // DetectResourceTimerJob タイマー起動でのリソース情報収集ジョブ 9 | func DetectResourceTimerJob(timerDuration time.Duration) *core.TimerJob { 10 | return core.NewTimerJob("DetectResource", startDetectResource, timerDuration) 11 | } 12 | 13 | func startDetectResource(queue *core.Queue, option *core.Option, job core.JobAPI) { 14 | queue.PushRequest("detect-resource-all", nil) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.7.1-alpine 2 | LABEL maintainer="Kazumichi Yamamoto " 3 | 4 | RUN apk add --no-cache --update ca-certificates git && \ 5 | go get github.com/stretchr/testify/assert && \ 6 | go get golang.org/x/tools/cmd/godoc && \ 7 | go get -u github.com/golang/lint/golint 8 | 9 | ENV SRC=$GOPATH/src/github.com/sacloud/libsacloud/ 10 | ADD . $SRC 11 | WORKDIR $SRC 12 | 13 | ENTRYPOINT [ "go" ] 14 | CMD [ "test", "-v", "./..." ] 15 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/license.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // License ライセンス 6 | type License struct { 7 | *Resource 8 | // Name 名称 9 | Name string `json:",omitempty"` 10 | // Description 説明 11 | Description string `json:",omitempty"` 12 | // CreatedAt 作成日時 13 | CreatedAt *time.Time `json:",omitempty"` 14 | // ModifiedAt 変更日時 15 | ModifiedAt *time.Time `json:",omitempty"` 16 | // LicenseInfo ライセンス情報 17 | LicenseInfo *ProductLicense `json:",omitempty"` 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/product_license.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // ProductLicense ライセンスプラン 6 | type ProductLicense struct { 7 | *Resource 8 | // Name 名称 9 | Name string `json:",omitempty"` 10 | // ServiceClass サービスクラス 11 | ServiceClass string `json:",omitempty"` 12 | // TermsOfUse 利用規約 13 | TermsOfUse string `json:",omitempty"` 14 | // CreatedAt 作成日時 15 | CreatedAt *time.Time `json:",omitempty"` 16 | // ModifiedAt 変更日時 17 | ModifiedAt *time.Time `json:",omitempty"` 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/ostype/archive_ostype.go: -------------------------------------------------------------------------------- 1 | // Package ostype is define OS type of SakuraCloud public archive 2 | package ostype 3 | 4 | // ArchiveOSTypes パブリックアーカイブOS種別 5 | type ArchiveOSTypes int 6 | 7 | const ( 8 | // CentOS OS種別:CentOS 9 | CentOS ArchiveOSTypes = iota 10 | // Ubuntu OS種別:Ubuntu 11 | Ubuntu 12 | // Debian OS種別:Debian 13 | Debian 14 | // VyOS OS種別:VyOS 15 | VyOS 16 | // CoreOS OS種別:CoreOS 17 | CoreOS 18 | // Kusanagi OS種別:Kusanagi(CentOS) 19 | Kusanagi 20 | // Custom OS種別:カスタム 21 | Custom 22 | ) 23 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/ftp_server.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // FTPServer FTPサーバー接続情報 4 | type FTPServer struct { 5 | // HostName FTPサーバーホスト名 6 | HostName string `json:",omitempty"` 7 | // IPAddress FTPサーバー IPアドレス 8 | IPAddress string `json:",omitempty"` 9 | // User 接続ユーザー名 10 | User string `json:",omitempty"` 11 | // Password パスワード 12 | Password string `json:",omitempty"` 13 | } 14 | 15 | // FTPOpenRequest FTP接続オープンリクエスト 16 | type FTPOpenRequest struct { 17 | // ChangePassword パスワード変更フラグ 18 | ChangePassword bool //省略不可 19 | } 20 | -------------------------------------------------------------------------------- /job/core/job_request.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | // JobRouterFunc ジョブキューでのルーティング処理用関数シグニチャ 4 | type JobRouterFunc func(*Queue, *Option, JobRequestAPI) 5 | 6 | // JobRequestAPI ジョブキューへのルーティング要求時パラメータ 7 | type JobRequestAPI interface { 8 | GetName() string 9 | GetPayload() interface{} 10 | } 11 | 12 | type jobRequest struct { 13 | name string 14 | payload interface{} 15 | } 16 | 17 | // GetName ジョブ名称の取得 18 | func (w *jobRequest) GetName() string { 19 | return w.name 20 | } 21 | 22 | // GetPayload ペイロードの取得 23 | func (w *jobRequest) GetPayload() interface{} { 24 | return w.payload 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/ipv6addr.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // IPv6Addr IPアドレス(IPv6) 4 | type IPv6Addr struct { 5 | // HostName ホスト名 6 | HostName string `json:",omitempty"` 7 | // IPv6Addr IPv6アドレス 8 | IPv6Addr string `json:",omitempty"` 9 | // Interface インターフェース 10 | Interface *Internet `json:",omitempty"` 11 | // IPv6Net IPv6サブネット 12 | IPv6Net *IPv6Net `json:",omitempty"` 13 | } 14 | 15 | // CreateNewIPv6Addr IPv6アドレス作成 16 | func CreateNewIPv6Addr() *IPv6Addr { 17 | return &IPv6Addr{ 18 | IPv6Net: &IPv6Net{ 19 | Resource: &Resource{}, 20 | }, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/icon.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // Icon アイコン 6 | type Icon struct { 7 | *Resource 8 | // URL アイコンURL 9 | URL string `json:",omitempty"` 10 | // Name 名称 11 | Name string `json:",omitempty"` 12 | // Image 画像データBase64文字列(Sizeパラメータ指定時 or 画像アップロード時に利用) 13 | Image string `json:",omitempty"` 14 | // Scope スコープ 15 | Scope string `json:",omitempty"` 16 | *EAvailability 17 | // CreatedAt 作成日時 18 | CreatedAt *time.Time `json:",omitempty"` 19 | // ModifiedAt 変更日時 20 | ModifiedAt *time.Time `json:",omitempty"` 21 | *TagsType 22 | } 23 | 24 | // Image 画像データBASE64文字列 25 | type Image string 26 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | test: 5 | build: . 6 | environment: 7 | - SAKURACLOUD_ACCESS_TOKEN 8 | - SAKURACLOUD_ACCESS_TOKEN_SECRET 9 | - SAKURACLOUD_REGION 10 | volumes: 11 | - .:/go/src/github.com/sacloud/libsacloud 12 | 13 | godoc: 14 | build: . 15 | entrypoint: 16 | - godoc 17 | command: -http=":6060" 18 | ports: 19 | - 6060:6060 20 | environment: 21 | - SAKURACLOUD_ACCESS_TOKEN 22 | - SAKURACLOUD_ACCESS_TOKEN_SECRET 23 | - SAKURACLOUD_REGION 24 | volumes: 25 | - .:/go/src/github.com/sacloud/libsacloud 26 | -------------------------------------------------------------------------------- /vendor/github.com/mackerelio/mackerel-client-go/Makefile: -------------------------------------------------------------------------------- 1 | test: lint gofmt 2 | go test -v ./... 3 | 4 | testdeps: 5 | go get -d -v -t ./... 6 | go get github.com/golang/lint/golint 7 | go get golang.org/x/tools/cmd/cover 8 | go get github.com/axw/gocov/gocov 9 | go get github.com/mattn/goveralls 10 | 11 | LINT_RET = .golint.txt 12 | lint: testdeps 13 | go tool vet . 14 | rm -f $(LINT_RET) 15 | golint ./... | tee $(LINT_RET) 16 | test ! -s $(LINT_RET) 17 | 18 | GOFMT_RET = .gofmt.txt 19 | gofmt: testdeps 20 | rm -f $(GOFMT_RET) 21 | gofmt -s -d *.go | tee $(GOFMT_RET) 22 | test ! -s $(GOFMT_RET) 23 | 24 | cover: testdeps 25 | goveralls 26 | 27 | .PHONY: test testdeps lint gofmt cover 28 | -------------------------------------------------------------------------------- /vendor/github.com/mackerelio/mackerel-client-go/org.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | // Org information 9 | type Org struct { 10 | Name string `json:"name"` 11 | } 12 | 13 | // GetOrg get the org 14 | func (c *Client) GetOrg() (*Org, error) { 15 | req, err := http.NewRequest("GET", c.urlFor("/api/v0/org").String(), nil) 16 | if err != nil { 17 | return nil, err 18 | } 19 | resp, err := c.Request(req) 20 | defer closeResponse(resp) 21 | if err != nil { 22 | return nil, err 23 | } 24 | var data Org 25 | err = json.NewDecoder(resp.Body).Decode(&data) 26 | if err != nil { 27 | return nil, err 28 | } 29 | return &data, nil 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/note.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // Note スタートアップスクリプト 6 | type Note struct { 7 | *Resource 8 | // Name 名称 9 | Name string 10 | // Class クラス 11 | Class string `json:",omitempty"` 12 | // Scope スコープ 13 | Scope string `json:",omitempty"` 14 | // Content スクリプト本体 15 | Content string `json:",omitempty"` 16 | // Description 説明 17 | Description string `json:",omitempty"` 18 | *EAvailability 19 | // CreatedAt 作成日時 20 | CreatedAt *time.Time `json:",omitempty"` 21 | // ModifiedAt 変更日時 22 | ModifiedAt *time.Time `json:",omitempty"` 23 | // Icon アイコン 24 | Icon *Icon `json:",omitempty"` 25 | *TagsType 26 | //TODO Remarkオブジェクトのパース 27 | } 28 | -------------------------------------------------------------------------------- /job/core/timer_job.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "time" 4 | 5 | // TimerJobAPI タイマー起動されるジョブを表すインターフェイス 6 | type TimerJobAPI interface { 7 | JobAPI 8 | GetTickerDuration() time.Duration 9 | } 10 | 11 | // TimerJob タイマー起動されるジョブ 12 | type TimerJob struct { 13 | *Job 14 | TickerDuration time.Duration 15 | } 16 | 17 | // GetTickerDuration タイマー起動間隔の取得 18 | func (j *TimerJob) GetTickerDuration() time.Duration { 19 | return j.TickerDuration 20 | } 21 | 22 | // NewTimerJob タイマー起動されるジョブの作成 23 | func NewTimerJob(name string, workerFunc WorkerFunc, tickerDuration time.Duration) *TimerJob { 24 | return &TimerJob{ 25 | Job: NewJob(name, workerFunc, nil), 26 | TickerDuration: tickerDuration, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /job/core/option_test.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "testing" 6 | ) 7 | 8 | func TestValidateOption(t *testing.T) { 9 | 10 | opt := NewOption() 11 | 12 | errors := opt.Validate() 13 | assert.True(t, len(errors) > 0) 14 | 15 | // AccessToken 16 | opt.SakuraCloudOption.AccessToken = "test" 17 | 18 | errors = opt.Validate() 19 | assert.True(t, len(errors) > 0) 20 | 21 | // AccessTokenSecret 22 | opt.SakuraCloudOption.AccessTokenSecret = "test" 23 | 24 | errors = opt.Validate() 25 | assert.True(t, len(errors) > 0) 26 | 27 | // Mackerel APIKey 28 | opt.MackerelOption.APIKey = "test" 29 | 30 | errors = opt.Validate() 31 | assert.Empty(t, errors) 32 | 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/icon.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "github.com/sacloud/libsacloud/sacloud" 4 | 5 | // IconAPI アイコンAPI 6 | type IconAPI struct { 7 | *baseAPI 8 | } 9 | 10 | // NewIconAPI アイコンAPI作成 11 | func NewIconAPI(client *Client) *IconAPI { 12 | return &IconAPI{ 13 | &baseAPI{ 14 | client: client, 15 | FuncGetResourceURL: func() string { 16 | return "icon" 17 | }, 18 | }, 19 | } 20 | } 21 | 22 | // GetImage アイコン画像データ(BASE64文字列)取得 23 | func (api *IconAPI) GetImage(id int64, size string) (*sacloud.Image, error) { 24 | 25 | res := &sacloud.Response{} 26 | err := api.read(id, map[string]string{"Size": size}, res) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return res.Image, nil 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/product_disk.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // ProductDisk ディスクプラン 4 | type ProductDisk struct { 5 | *Resource 6 | // StorageClass ストレージクラス 7 | StorageClass string `json:",omitempty"` 8 | // Name 名称 9 | Name string `json:",omitempty"` 10 | // Description 説明 11 | Description string `json:",omitempty"` 12 | *EAvailability 13 | // Size サイズ 14 | Size []struct { 15 | // SizeMB サイズ(MB単位) 16 | SizeMB int `json:",omitempty"` 17 | // DisplaySize 表示サイズ 18 | DisplaySize int `json:",omitempty"` 19 | // DisplaySuffix 表示さフィックス 20 | DisplaySuffix string `json:",omitempty"` 21 | *EAvailability 22 | // ServiceClass サービスクラス 23 | ServiceClass string `json:",omitempty"` 24 | } `json:",omitempty"` 25 | } 26 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | OS="darwin linux windows" 6 | ARCH="amd64 386" 7 | 8 | rm -Rf bin/ 9 | mkdir bin/ 10 | 11 | for GOOS in $OS; do 12 | for GOARCH in $ARCH; do 13 | arch="$GOOS-$GOARCH" 14 | binary="sackerel" 15 | if [ "$GOOS" = "windows" ]; then 16 | binary="${binary}.exe" 17 | fi 18 | echo "Building $binary $arch" 19 | GOOS=$GOOS GOARCH=$GOARCH CGO_ENABLED=0 \ 20 | govendor build \ 21 | -ldflags "-s -w -X `go list ./version`.Revision=`git rev-parse --short HEAD 2>/dev/null`" \ 22 | -o $binary \ 23 | main.go 24 | zip -r "bin/sackerel_$arch" $binary 25 | rm -f $binary 26 | done 27 | done 28 | -------------------------------------------------------------------------------- /job/runner.go: -------------------------------------------------------------------------------- 1 | package job 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/sackerel/job/core" 6 | ) 7 | 8 | // Run sackerelメイン処理 9 | func Run(option *core.Option) error { 10 | 11 | // setup jobs environments 12 | jobQueue := core.NewQueue(option.QueueBufSizes()) 13 | dispatcher := NewDispatcher(option, jobQueue) 14 | 15 | // start HealthCheck WebServer 16 | if !option.DisableHealthCheck { 17 | healthCheckServer := NewHealthCheckServer(option.HealthCheckWebServerPort) 18 | healthCheckServer.ListenAndServe() 19 | jobQueue.PushInfo(fmt.Sprintf("HealthCheck WebServer started on [:%d]", option.HealthCheckWebServerPort)) 20 | } 21 | 22 | // start jobs 23 | err := dispatcher.Dispatch() 24 | 25 | if err != nil { 26 | return err 27 | } 28 | 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /scripts/build_on_docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | DOCKER_IMAGE_NAME="sackerel-build" 6 | DOCKER_CONTAINER_NAME="sackerel-build-container" 7 | 8 | if [[ $(docker ps -a | grep $DOCKER_CONTAINER_NAME) != "" ]]; then 9 | docker rm -f $DOCKER_CONTAINER_NAME 2>/dev/null 10 | fi 11 | 12 | docker build -t $DOCKER_IMAGE_NAME -f scripts/Dockerfile.build . 13 | 14 | docker run --name $DOCKER_CONTAINER_NAME \ 15 | -e SAKURACLOUD_ACCESS_TOKEN \ 16 | -e SAKURACLOUD_ACCESS_TOKEN_SECRET \ 17 | -e SAKURACLOUD_TRACE_MODE \ 18 | -e TESTARGS \ 19 | $DOCKER_IMAGE_NAME make "$@" 20 | if [[ "$@" == *"build"* ]]; then 21 | docker cp $DOCKER_CONTAINER_NAME:/go/src/github.com/sacloud/sackerel/bin ./ 22 | fi 23 | docker rm -f $DOCKER_CONTAINER_NAME 2>/dev/null 24 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/cdrom.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // CDROM ISOイメージ(CDROM) 6 | type CDROM struct { 7 | *Resource 8 | // StorageClass ストレージクラス 9 | StorageClass string `json:",omitempty"` 10 | // Name 名称 11 | Name string `json:",omitempty"` 12 | // Description 説明 13 | Description string `json:",omitempty"` 14 | // SizeMB サイズ(MB単位) 15 | SizeMB int `json:",omitempty"` 16 | // Scope スコープ 17 | Scope string `json:",omitempty"` 18 | *EAvailability 19 | // ServiceClass サービスクラス 20 | ServiceClass string `json:",omitempty"` 21 | // CreatedAt 作成日時 22 | CreatedAt *time.Time `json:",omitempty"` 23 | // Icon アイコン 24 | Icon string `json:",omitempty"` 25 | // Storage ストレージ 26 | Storage *Storage `json:",omitempty"` 27 | *TagsType 28 | } 29 | -------------------------------------------------------------------------------- /scripts/run_on_docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 注:ポート番号は固定 4 | docker run -it --rm \ 5 | --name sackerel \ 6 | -p 39700:39700 \ 7 | -e SAKURACLOUD_ACCESS_TOKEN \ 8 | -e SAKURACLOUD_ACCESS_TOKEN_SECRET \ 9 | -e SAKURACLOUD_ZONES \ 10 | -e SAKURACLOUD_TRACE_MODE \ 11 | -e MACKEREL_APIKEY \ 12 | -e MACKEREL_TRACE_MODE \ 13 | -e SACKEREL_TIMER_JOB_INTERVAL \ 14 | -e SACKEREL_COLLECT_METRICS_DURATION \ 15 | -e SACKEREL_API_CALL_INTERVAL \ 16 | -e SACKEREL_JOB_QUEUE_SIZE \ 17 | -e SACKEREL_SAKURA_API_REQEST_QUEUE_SIZE \ 18 | -e SACKEREL_MACKEREL_API_REQEST_QUEUE_SIZE \ 19 | -e SACKEREL_DISABLE_HEALTHCHECK \ 20 | -e SACKEREL_SKIP_INIT \ 21 | -e SACKEREL_TRACE_LOG \ 22 | -e SACKEREL_INFO_LOG \ 23 | -e SACKEREL_WARN_LOG \ 24 | -e SACKEREL_ERROR_LOG \ 25 | sackerel:latest $@ -------------------------------------------------------------------------------- /scripts/run_on_docker_daemon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 注:ポート番号は固定 4 | docker run -d \ 5 | --name sackerel \ 6 | -p 39700:39700 \ 7 | -e SAKURACLOUD_ACCESS_TOKEN \ 8 | -e SAKURACLOUD_ACCESS_TOKEN_SECRET \ 9 | -e SAKURACLOUD_ZONES \ 10 | -e SAKURACLOUD_TRACE_MODE \ 11 | -e MACKEREL_APIKEY \ 12 | -e MACKEREL_TRACE_MODE \ 13 | -e SACKEREL_TIMER_JOB_INTERVAL \ 14 | -e SACKEREL_COLLECT_METRICS_DURATION \ 15 | -e SACKEREL_API_CALL_INTERVAL \ 16 | -e SACKEREL_JOB_QUEUE_SIZE \ 17 | -e SACKEREL_SAKURA_API_REQEST_QUEUE_SIZE \ 18 | -e SACKEREL_MACKEREL_API_REQEST_QUEUE_SIZE \ 19 | -e SACKEREL_DISABLE_HEALTHCHECK \ 20 | -e SACKEREL_SKIP_INIT \ 21 | -e SACKEREL_TRACE_LOG \ 22 | -e SACKEREL_INFO_LOG \ 23 | -e SACKEREL_WARN_LOG \ 24 | -e SACKEREL_ERROR_LOG \ 25 | sackerel:latest $@ -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/zone.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // Zone ゾーン 4 | type Zone struct { 5 | *Resource 6 | // Name 名称 7 | Name string `json:",omitempty"` 8 | // Description 説明 9 | Description string `json:",omitempty"` 10 | // IsDummy ダミーフラグ 11 | IsDummy bool `json:",omitempty"` 12 | // VNCProxy VPCプロキシ 13 | VNCProxy struct { 14 | // HostName ホスト名 15 | HostName string `json:",omitempty"` 16 | // IPAddress IPアドレス 17 | IPAddress string `json:",omitempty"` 18 | } `json:",omitempty"` 19 | // FTPServer FTPサーバー 20 | FTPServer struct { 21 | // HostName ホスト名 22 | HostName string `json:",omitempty"` 23 | // IPAddress IPアドレス 24 | IPAddress string `json:",omitempty"` 25 | } `json:",omitempty"` 26 | // Region リージョン 27 | Region *Region `json:",omitempty"` 28 | } 29 | -------------------------------------------------------------------------------- /vendor/gopkg.in/urfave/cli.v2/cli.go: -------------------------------------------------------------------------------- 1 | // Package cli provides a minimal framework for creating and organizing command line 2 | // Go applications. cli is designed to be easy to understand and write, the most simple 3 | // cli application can be written as follows: 4 | // func main() { 5 | // (&cli.App{}).Run(os.Args) 6 | // } 7 | // 8 | // Of course this application does not do much, so let's make this an actual application: 9 | // func main() { 10 | // app := &cli.App{ 11 | // Name: "greet", 12 | // Usage: "say a greeting", 13 | // Action: func(c *cli.Context) error { 14 | // println("Greetings") 15 | // }, 16 | // } 17 | // 18 | // app.Run(os.Args) 19 | // } 20 | package cli 21 | 22 | //go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go 23 | -------------------------------------------------------------------------------- /job/health_check_server.go: -------------------------------------------------------------------------------- 1 | package job 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/sackerel/job/core" 6 | "net/http" 7 | ) 8 | 9 | // HealthCheckServer ヘルスチェック用Webサーバー 10 | type HealthCheckServer struct { 11 | Port int 12 | } 13 | 14 | // NewHealthCheckServer HealthCheckServerの新規作成 15 | func NewHealthCheckServer(port int) *HealthCheckServer { 16 | return &HealthCheckServer{ 17 | Port: port, 18 | } 19 | } 20 | 21 | // ListenAndServe ヘルスチェック用に指定ポートでリッスンし、httpリクエストに対し応答する 22 | func (s *HealthCheckServer) ListenAndServe() { 23 | 24 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 25 | w.Write([]byte("ok")) 26 | }) 27 | 28 | if s.Port == 0 { 29 | s.Port = core.DefaultHealthCheckWebServerPort 30 | } 31 | 32 | go http.ListenAndServe(fmt.Sprintf(":%d", s.Port), nil) 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2013 Dave Collins 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/Makefile: -------------------------------------------------------------------------------- 1 | TEST?=$$(go list ./... | grep -v vendor) 2 | VETARGS?=-all 3 | GOFMT_FILES?=$$(find . -name '*.go' | grep -v vendor) 4 | 5 | default: test vet 6 | 7 | run: 8 | go run $(CURDIR)/main.go --disable-healthcheck $(ARGS) 9 | 10 | test: vet 11 | go test ./sacloud $(TESTARGS) -v -timeout=30m -parallel=4 ; 12 | 13 | test-api: vet 14 | go test ./api $(TESTARGS) -v -timeout=30m -parallel=4 ; 15 | 16 | test-builder: vet 17 | go test ./builder $(TESTARGS) -v -timeout=30m -parallel=4 ; 18 | 19 | test-all: test test-api test-builder 20 | 21 | vet: golint 22 | go vet ./... 23 | 24 | golint: fmt 25 | golint ./... 26 | 27 | fmt: 28 | gofmt -s -l -w $(GOFMT_FILES) 29 | 30 | godoc: 31 | docker-compose up godoc 32 | 33 | .PHONY: default test vet fmt golint test-api test-builder test-all run 34 | -------------------------------------------------------------------------------- /vendor/github.com/mackerelio/mackerel-client-go/graph_defs.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | // GraphDefsParam parameters for posting graph definitions 4 | type GraphDefsParam struct { 5 | Name string `json:"name"` 6 | DisplayName string `json:"displayName"` 7 | Unit string `json:"unit"` 8 | Metrics []*GraphDefsMetric `json:"metrics"` 9 | } 10 | 11 | // GraphDefsMetric graph metric 12 | type GraphDefsMetric struct { 13 | Name string `json:"name"` 14 | DisplayName string `json:"displayName"` 15 | IsStacked bool `json:"isStacked"` 16 | } 17 | 18 | // CreateGraphDefs create graph defs 19 | func (c *Client) CreateGraphDefs(payloads []*GraphDefsParam) error { 20 | resp, err := c.PostJSON("/api/v0/graph-defs/create", payloads) 21 | defer closeResponse(resp) 22 | return err 23 | } 24 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/public_price.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // PublicPrice 料金 4 | type PublicPrice struct { 5 | // DisplayName 表示名 6 | DisplayName string `json:",omitempty"` 7 | // IsPublic 公開フラグ 8 | IsPublic bool `json:",omitempty"` 9 | // Price 価格 10 | Price struct { 11 | // Base 基本料金 12 | Base int `json:",omitempty"` 13 | // Daily 日単位料金 14 | Daily int `json:",omitempty"` 15 | // Hourly 時間単位料金 16 | Hourly int `json:",omitempty"` 17 | // Monthly 分単位料金 18 | Monthly int `json:",omitempty"` 19 | // Zone ゾーン 20 | Zone string `json:",omitempty"` 21 | } 22 | // ServiceClassID サービスクラスID 23 | ServiceClassID int `json:",omitempty"` 24 | // ServiceClassName サービスクラス名 25 | ServiceClassName string `json:",omitempty"` 26 | // ServiceClassPath サービスクラスパス 27 | ServiceClassPath string `json:",omitempty"` 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/internet.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // Internet ルーター 8 | type Internet struct { 9 | *Resource 10 | // Name 名称 11 | Name string `json:",omitempty"` 12 | // Description 説明 13 | Description string `json:",omitempty"` 14 | // BandWidthMbps 帯域 15 | BandWidthMbps int `json:",omitempty"` 16 | // NetworkMaskLen ネットワークマスク長 17 | NetworkMaskLen int `json:",omitempty"` 18 | // Scope スコープ 19 | Scope EScope `json:",omitempty"` 20 | // ServiceClass サービスクラス 21 | ServiceClass string `json:",omitempty"` 22 | // CreatedAt 作成日時 23 | CreatedAt *time.Time `json:",omitempty"` 24 | // Icon アイコン 25 | Icon *Icon `json:",omitempty"` 26 | // Switch スイッチ 27 | Switch *Switch `json:",omitempty"` 28 | *TagsType 29 | 30 | //TODO Zone 31 | // Zone *Zone `json:",omitempty"` 32 | 33 | } 34 | -------------------------------------------------------------------------------- /vendor/gopkg.in/urfave/cli.v2/GNUmakefile: -------------------------------------------------------------------------------- 1 | default: test 2 | 3 | deps: 4 | go get golang.org/x/tools/cmd/goimports || true 5 | go get github.com/urfave/gfmrun/... || true 6 | go list ./... \ 7 | | xargs go list -f '{{ join .Deps "\n" }}{{ printf "\n" }}{{ join .TestImports "\n" }}' \ 8 | | grep -v github.com/urfave/cli \ 9 | | xargs go get 10 | @if [ ! -f node_modules/.bin/markdown-toc ]; then \ 11 | npm install markdown-toc ; \ 12 | fi 13 | 14 | gen: deps 15 | ./runtests gen 16 | 17 | vet: 18 | ./runtests vet 19 | 20 | gfmrun: 21 | ./runtests gfmrun 22 | 23 | v1-to-v2: 24 | ./cli-v1-to-v2 --selftest 25 | 26 | migrations: 27 | ./runtests migrations 28 | 29 | toc: 30 | ./runtests toc 31 | 32 | test: deps 33 | ./runtests test 34 | 35 | all: gen vet test gfmrun v1-to-v2 migrations toc 36 | 37 | .PHONY: default gen vet test gfmrun migrations toc v1-to-v2 deps all 38 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/subnet.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // Subnet IPv4サブネット 6 | type Subnet struct { 7 | *Resource 8 | // DefaultRoute デフォルトルート 9 | DefaultRoute string `json:",omitempty"` 10 | // CreatedAt 作成日時 11 | CreatedAt *time.Time `json:",omitempty"` 12 | // IPAddresses IPv4アドレス範囲 13 | IPAddresses []*IPAddress `json:",omitempty"` 14 | // NetworkAddress ネットワークアドレス 15 | NetworkAddress string `json:",omitempty"` 16 | // NetworkMaskLen ネットワークマスク長 17 | NetworkMaskLen int `json:",omitempty"` 18 | // ServiceClass サービスクラス 19 | ServiceClass string `json:",omitempty"` 20 | // ServiceID サービスID 21 | ServiceID int64 `json:",omitempty"` 22 | // StaticRoute スタティックルート 23 | StaticRoute string `json:",omitempty"` 24 | // Switch スイッチ 25 | Switch *Switch `json:",omitempty"` 26 | // Internet ルーター 27 | Internet *Internet `json:",omitempty"` 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/ipv6net.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // IPv6Net IPv6ネットワーク(サブネット) 6 | type IPv6Net struct { 7 | *Resource 8 | 9 | // IPv6Prefix IPv6プレフィックス 10 | IPv6Prefix string `json:",omitempty"` 11 | // IPv6PrefixLen IPv6プレフィックス長 12 | IPv6PrefixLen int `json:",omitempty"` 13 | // IPv6PrefixTail IPv6プレフィックス末尾 14 | IPv6PrefixTail string `json:",omitempty"` 15 | // IPv6Table IPv6テーブル 16 | IPv6Table *Resource `json:",omitempty"` 17 | // NamedIPv6AddrCount 名前付きIPv6アドレス数 18 | NamedIPv6AddrCount int `json:",omitempty"` 19 | // ServiceID サービスID 20 | ServiceID int64 `json:",omitempty"` 21 | // ServiceClass サービスクラス 22 | ServiceClass string `json:",omitempty"` 23 | // Scope スコープ 24 | Scope string `json:",omitempty"` 25 | // CreatedAt 作成日時 26 | CreatedAt *time.Time `json:",omitempty"` 27 | // Switch スイッチ 28 | Switch *Switch `json:",omitempty"` 29 | } 30 | -------------------------------------------------------------------------------- /vendor/gopkg.in/urfave/cli.v2/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | os: Windows Server 2012 R2 4 | 5 | clone_folder: c:\gopath\src\github.com\urfave\cli 6 | 7 | cache: 8 | - node_modules 9 | 10 | environment: 11 | GOPATH: C:\gopath 12 | GOVERSION: 1.6 13 | PYTHON: C:\Python27-x64 14 | PYTHON_VERSION: 2.7.x 15 | PYTHON_ARCH: 64 16 | 17 | install: 18 | - set PATH=%GOPATH%\bin;C:\go\bin;%PATH% 19 | - go version 20 | - go env 21 | - go get github.com/urfave/gfmrun/... 22 | - rmdir c:\gopath\src\gopkg.in\urfave\cli.v2 /s /q 23 | - rmdir c:\gopath\pkg /s /q 24 | - git clone . c:\gopath\src\gopkg.in\urfave\cli.v2 25 | - go get -v -t ./... 26 | - if not exist node_modules\.bin\markdown-toc npm install markdown-toc 27 | 28 | build_script: 29 | - python runtests vet 30 | - python runtests test 31 | - python runtests gfmrun 32 | - python cli-v1-to-v2 --selftest 33 | - python runtests migrations 34 | - python runtests toc 35 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/bridge.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // Bridge ブリッジ 6 | type Bridge struct { 7 | *Resource 8 | // Name 名称 9 | Name string `json:",omitempty"` 10 | // Description 説明 11 | Description string `json:",omitempty"` 12 | // Info インフォ 13 | Info *struct { 14 | // Switches 接続スイッチリスト 15 | Switches []Switch 16 | } 17 | // ServiceClass サービスクラス 18 | ServiceClass string `json:",omitempty"` 19 | // CreatedAt 作成日時 20 | CreatedAt *time.Time `json:",omitempty"` 21 | // Region リージョン 22 | Region *Region `json:",omitempty"` 23 | // SwitchInZone ゾーン内接続スイッチ 24 | SwitchInZone *struct { 25 | *Resource 26 | // Name 名称 27 | Name string `json:",omitempty"` 28 | // ServerCount 接続サーバー数 29 | ServerCount int `json:",omitempty"` 30 | // ApplianceCount 接続アプライアンス数 31 | ApplianceCount int `json:",omitempty"` 32 | // Scope スコープ 33 | Scope string `json:",omitempty"` 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/interface.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // Interface インターフェース(NIC) 4 | type Interface struct { 5 | *Resource 6 | // MACAddress MACアドレス 7 | MACAddress string `json:",omitempty"` 8 | // IPAddress IPアドレス 9 | IPAddress string `json:",omitempty"` 10 | // UserIPAddress ユーザー指定IPアドレス 11 | UserIPAddress string `json:",omitempty"` 12 | // HostName ホスト名 13 | HostName string `json:",omitempty"` 14 | // Server 接続先サーバー 15 | Server *Server `json:",omitempty"` 16 | // Switch 接続先スイッチ 17 | Switch *Switch `json:",omitempty"` 18 | // PacketFilter 適用パケットフィルタ 19 | PacketFilter *PacketFilter `json:",omitempty"` 20 | } 21 | 22 | // SetNewServerID サーバーIDの設定 23 | func (i *Interface) SetNewServerID(id int64) { 24 | i.Server = &Server{Resource: &Resource{ID: id}} 25 | } 26 | 27 | // SetNewSwitchID スイッチIDの設定 28 | func (i *Interface) SetNewSwitchID(id int64) { 29 | i.Switch = &Switch{Resource: &Resource{ID: id}} 30 | } 31 | -------------------------------------------------------------------------------- /job/router.go: -------------------------------------------------------------------------------- 1 | package job 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/sackerel/job/core" 6 | ) 7 | 8 | // Router ジョブキューに対するルーティング定義/処理を提供する 9 | type Router struct { 10 | queue *core.Queue 11 | option *core.Option 12 | routes map[string]core.JobRouterFunc 13 | } 14 | 15 | // NewRouter Routerの新規作成 16 | func NewRouter(queue *core.Queue, option *core.Option) *Router { 17 | r := &Router{ 18 | queue: queue, 19 | option: option, 20 | } 21 | r.buildRouteDefines() 22 | return r 23 | } 24 | 25 | // Routing ジョブキューへの処理リクエストを定義に従いルーティングし、適切なワーカーを呼び出す 26 | func (r *Router) Routing(req core.JobRequestAPI) { 27 | 28 | payload := req.GetPayload() 29 | r.queue.PushTrace(fmt.Sprintf("request => '%s' payload => (%#v)", req.GetName(), payload)) 30 | 31 | if route, ok := r.routes[req.GetName()]; ok { 32 | route(r.queue, r.option, req) 33 | } else { 34 | r.queue.PushWarn(fmt.Errorf("Route('%s') is not found.", req.GetName())) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/auth_status.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | ) 7 | 8 | // AuthStatusAPI 認証状態API 9 | type AuthStatusAPI struct { 10 | *baseAPI 11 | } 12 | 13 | // NewAuthStatusAPI 認証状態API作成 14 | func NewAuthStatusAPI(client *Client) *AuthStatusAPI { 15 | return &AuthStatusAPI{ 16 | &baseAPI{ 17 | client: client, 18 | FuncGetResourceURL: func() string { 19 | return "auth-status" 20 | }, 21 | }, 22 | } 23 | } 24 | 25 | // Read 読み取り 26 | func (api *AuthStatusAPI) Read() (*sacloud.AuthStatus, error) { 27 | 28 | data, err := api.client.newRequest("GET", api.getResourceURL(), nil) 29 | if err != nil { 30 | return nil, err 31 | } 32 | var res sacloud.AuthStatus 33 | if err := json.Unmarshal(data, &res); err != nil { 34 | return nil, err 35 | } 36 | return &res, nil 37 | } 38 | 39 | // Find 検索 40 | func (api *AuthStatusAPI) Find() (*sacloud.AuthStatus, error) { 41 | return api.Read() 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/bill.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // Bill 請求情報 6 | type Bill struct { 7 | // Amount 金額 8 | Amount int64 `json:",omitempty"` 9 | // BillID 請求ID 10 | BillID int64 `json:",omitempty"` 11 | // Date 請求日 12 | Date *time.Time `json:",omitempty"` 13 | // MemberID 会員ID 14 | MemberID string `json:",omitempty"` 15 | // Paid 支払済フラグ 16 | Paid bool `json:",omitempty"` 17 | // PayLimit 支払い期限 18 | PayLimit *time.Time `json:",omitempty"` 19 | // PaymentClassID 支払いクラスID 20 | PaymentClassID int `json:",omitempty"` 21 | } 22 | 23 | // BillDetail 支払い明細情報 24 | type BillDetail struct { 25 | // Amount 金額 26 | Amount int64 `json:",omitempty"` 27 | // ContractID 契約ID 28 | ContractID int64 `json:",omitempty"` 29 | // Description 説明 30 | Description string `json:",omitempty"` 31 | // Index インデックス 32 | Index int `json:",omitempty"` 33 | // ServiceClassID サービスクラスID 34 | ServiceClassID int64 `json:",omitempty"` 35 | // Usage 秒数 36 | Usage int64 `json:",omitempty"` 37 | // Zone ゾーン 38 | Zone string `json:",omitempty"` 39 | } 40 | -------------------------------------------------------------------------------- /job/core/job.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "fmt" 4 | 5 | // WorkerFunc ジョブキューでのワーカーが保有する処理用関数シグニチャ 6 | type WorkerFunc func(*Queue, *Option, JobAPI) 7 | 8 | // JobAPI ジョブキューでのジョブ(ワーカー呼び出し)を表すインターフェース 9 | type JobAPI interface { 10 | GetName() string 11 | GetPayload() interface{} 12 | Start(*Queue, *Option) 13 | } 14 | 15 | // Job ジョブキューでのジョブ定義 16 | type Job struct { 17 | Name string 18 | WorkerFunc WorkerFunc 19 | Payload interface{} 20 | } 21 | 22 | // Start ジョブ内のワーカー呼び出し 23 | func (w *Job) Start(queue *Queue, option *Option) { 24 | if w.WorkerFunc == nil { 25 | queue.PushError(fmt.Errorf("'%s': WorkerFunc is requied", w.GetName())) 26 | return 27 | } 28 | 29 | w.WorkerFunc(queue, option, w) 30 | } 31 | 32 | // GetName ジョブ名取得 33 | func (w *Job) GetName() string { 34 | return w.Name 35 | } 36 | 37 | // GetPayload ペイロード取得 38 | func (w *Job) GetPayload() interface{} { 39 | return w.Payload 40 | } 41 | 42 | // NewJob Jobの新規作成 43 | func NewJob(name string, workerFunc WorkerFunc, payload interface{}) *Job { 44 | return &Job{ 45 | Name: name, 46 | WorkerFunc: workerFunc, 47 | Payload: payload, 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /vendor/gopkg.in/urfave/cli.v2/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Jeremy Saenz & Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell 2 | 3 | Please consider promoting this project if you find it useful. 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without restriction, 8 | including without limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of the Software, 10 | and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 21 | OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 22 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/webaccel.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/sacloud/libsacloud/sacloud" 7 | ) 8 | 9 | // WebAccelAPI ウェブアクセラレータAPI 10 | type WebAccelAPI struct { 11 | *baseAPI 12 | } 13 | 14 | // NewWebAccelAPI ウェブアクセラレータAPI 15 | func NewWebAccelAPI(client *Client) *WebAccelAPI { 16 | return &WebAccelAPI{ 17 | &baseAPI{ 18 | client: client, 19 | apiRootSuffix: sakuraWebAccelAPIRootSuffix, 20 | FuncGetResourceURL: func() string { 21 | return "" 22 | }, 23 | }, 24 | } 25 | } 26 | 27 | // WebAccelDeleteCacheResponse ウェブアクセラレータ キャッシュ削除レスポンス 28 | type WebAccelDeleteCacheResponse struct { 29 | *sacloud.ResultFlagValue 30 | Results []*sacloud.DeleteCacheResult 31 | } 32 | 33 | // DeleteCache キャッシュ削除 34 | func (api *WebAccelAPI) DeleteCache(urls ...string) (*WebAccelDeleteCacheResponse, error) { 35 | 36 | type request struct { 37 | // URL 38 | URL []string 39 | } 40 | 41 | uri := fmt.Sprintf("%s/deletecache", api.getResourceURL()) 42 | 43 | data, err := api.client.newRequest("POST", uri, &request{URL: urls}) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | var res WebAccelDeleteCacheResponse 49 | if err := json.Unmarshal(data, &res); err != nil { 50 | return nil, err 51 | } 52 | return &res, nil 53 | } 54 | -------------------------------------------------------------------------------- /job/worker/mackerel/mackerel_test.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | mkr "github.com/mackerelio/mackerel-client-go" 5 | "github.com/sacloud/sackerel/job/core" 6 | "github.com/stretchr/testify/assert" 7 | "log" 8 | "os" 9 | "testing" 10 | ) 11 | 12 | var ( 13 | testSetupHandlers []func() 14 | testTearDownHandlers []func() 15 | mockOption *core.Option 16 | mockBlockQueue *core.Queue 17 | mackerelClient *mkr.Client 18 | ) 19 | 20 | func TestMain(m *testing.M) { 21 | //環境変数にトークン/シークレットがある場合のみテスト実施 22 | apiKey := os.Getenv("MACKEREL_APIKEY") 23 | 24 | if apiKey == "" { 25 | log.Println("Please Set ENV 'MACKEREL_APIKEY'") 26 | os.Exit(0) // exit normal 27 | } 28 | 29 | // setup mock option 30 | mockOption = core.NewOption() 31 | mockOption.MackerelOption.APIKey = apiKey 32 | 33 | // setup mock queue 34 | mockBlockQueue = core.NewQueue(1, 1, 1, 1) 35 | 36 | mackerelClient = getClient(mockOption) 37 | 38 | // setup test 39 | for _, f := range testSetupHandlers { 40 | f() 41 | } 42 | 43 | ret := m.Run() 44 | 45 | // teardown 46 | for _, f := range testTearDownHandlers { 47 | f() 48 | } 49 | 50 | os.Exit(ret) 51 | } 52 | 53 | func TestGetOrganization(t *testing.T) { 54 | 55 | org, err := mackerelClient.GetOrg() 56 | 57 | assert.NoError(t, err) 58 | assert.NotNil(t, org) 59 | assert.NotEmpty(t, org.Name) 60 | 61 | } 62 | -------------------------------------------------------------------------------- /vendor/gopkg.in/urfave/cli.v2/funcs.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | // BashCompleteFunc is an action to execute when the bash-completion flag is set 4 | type BashCompleteFunc func(*Context) 5 | 6 | // BeforeFunc is an action to execute before any subcommands are run, but after 7 | // the context is ready if a non-nil error is returned, no subcommands are run 8 | type BeforeFunc func(*Context) error 9 | 10 | // AfterFunc is an action to execute after any subcommands are run, but after the 11 | // subcommand has finished it is run even if Action() panics 12 | type AfterFunc func(*Context) error 13 | 14 | // ActionFunc is the action to execute when no subcommands are specified 15 | type ActionFunc func(*Context) error 16 | 17 | // CommandNotFoundFunc is executed if the proper command cannot be found 18 | type CommandNotFoundFunc func(*Context, string) 19 | 20 | // OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying 21 | // customized usage error messages. This function is able to replace the 22 | // original error messages. If this function is not set, the "Incorrect usage" 23 | // is displayed and the execution is interrupted. 24 | type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error 25 | 26 | // FlagStringFunc is used by the help generation to display a flag, which is 27 | // expected to be a single line. 28 | type FlagStringFunc func(Flag) string 29 | -------------------------------------------------------------------------------- /job/worker/sacloud/detect_router.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/api" 5 | "github.com/sacloud/sackerel/job/core" 6 | "reflect" 7 | ) 8 | 9 | // DetectRouterJob さくらのクラウド上からルーターを検出するジョブ 10 | func DetectRouterJob(payload interface{}) core.JobAPI { 11 | return core.NewJob("DetectRouter", detectRouter, payload) 12 | } 13 | 14 | func detectRouter(queue *core.Queue, option *core.Option, job core.JobAPI) { 15 | 16 | err := doActionPerZone(option, func(client *api.Client) error { 17 | 18 | res, err := client.Internet.Find() 19 | if err != nil { 20 | return err 21 | } 22 | 23 | for _, router := range res.Internet { 24 | 25 | // router.Switchでは情報が不足しているため、Switchのみ再取得する 26 | sw, err := client.Switch.Read(router.Switch.ID) 27 | if err != nil { 28 | return err 29 | } 30 | router.Switch = sw 31 | 32 | // !!HACK!! routerではなく、スイッチがタグを持っている 33 | if hasIgnoreTagWithInfoLog(sw, option.IgnoreTag, queue, router.ID, router.Name, reflect.TypeOf(router)) { 34 | continue 35 | } 36 | 37 | r := router 38 | payload := core.NewCreateHostPayload(&r, client.Zone, router.ID, reflect.TypeOf(router)) 39 | payload.MackerelHostStatus = core.MackerelHostStatusWorking 40 | 41 | queue.PushRequest("found-router", payload) 42 | } 43 | 44 | return nil 45 | }) 46 | 47 | if err != nil { 48 | queue.PushError(err) 49 | return 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /vendor/gopkg.in/urfave/cli.v2/args.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import "errors" 4 | 5 | var ( 6 | argsRangeErr = errors.New("index out of range") 7 | ) 8 | 9 | type Args interface { 10 | // Get returns the nth argument, or else a blank string 11 | Get(n int) string 12 | // First returns the first argument, or else a blank string 13 | First() string 14 | // Tail returns the rest of the arguments (not the first one) 15 | // or else an empty string slice 16 | Tail() []string 17 | // Len returns the length of the wrapped slice 18 | Len() int 19 | // Present checks if there are any arguments present 20 | Present() bool 21 | // Slice returns a copy of the internal slice 22 | Slice() []string 23 | } 24 | 25 | type args []string 26 | 27 | func (a *args) Get(n int) string { 28 | if len(*a) > n { 29 | return (*a)[n] 30 | } 31 | return "" 32 | } 33 | 34 | func (a *args) First() string { 35 | return a.Get(0) 36 | } 37 | 38 | func (a *args) Tail() []string { 39 | if a.Len() >= 2 { 40 | tail := []string((*a)[1:]) 41 | ret := make([]string, len(tail)) 42 | copy(ret, tail) 43 | return ret 44 | } 45 | return []string{} 46 | } 47 | 48 | func (a *args) Len() int { 49 | return len(*a) 50 | } 51 | 52 | func (a *args) Present() bool { 53 | return a.Len() != 0 54 | } 55 | 56 | func (a *args) Slice() []string { 57 | ret := make([]string, len(*a)) 58 | copy(ret, []string(*a)) 59 | return ret 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/ipaddress.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | ) 7 | 8 | // IPAddressAPI IPアドレスAPI 9 | type IPAddressAPI struct { 10 | *baseAPI 11 | } 12 | 13 | // NewIPAddressAPI IPアドレスAPI新規作成 14 | func NewIPAddressAPI(client *Client) *IPAddressAPI { 15 | return &IPAddressAPI{ 16 | &baseAPI{ 17 | client: client, 18 | FuncGetResourceURL: func() string { 19 | return "ipaddress" 20 | }, 21 | }, 22 | } 23 | } 24 | 25 | // Read 読み取り 26 | func (api *IPAddressAPI) Read(ip string) (*sacloud.IPAddress, error) { 27 | return api.request(func(res *sacloud.Response) error { 28 | var ( 29 | method = "GET" 30 | uri = fmt.Sprintf("%s/%s", api.getResourceURL(), ip) 31 | ) 32 | 33 | return api.baseAPI.request(method, uri, nil, res) 34 | }) 35 | 36 | } 37 | 38 | // Update 更新(ホスト名逆引き設定) 39 | func (api *IPAddressAPI) Update(ip string, hostName string) (*sacloud.IPAddress, error) { 40 | 41 | type request struct { 42 | // IPAddress 43 | IPAddress map[string]string 44 | } 45 | 46 | var ( 47 | method = "PUT" 48 | uri = fmt.Sprintf("%s/%s", api.getResourceURL(), ip) 49 | body = &request{IPAddress: map[string]string{}} 50 | ) 51 | body.IPAddress["HostName"] = hostName 52 | 53 | return api.request(func(res *sacloud.Response) error { 54 | return api.baseAPI.request(method, uri, body, res) 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /job/worker/sacloud/add_agent_tag.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/sackerel/job/core" 6 | ) 7 | 8 | // AddAgentTagJob エージェントタグ追加ジョブ 9 | func AddAgentTagJob(payload interface{}) core.JobAPI { 10 | return core.NewJob("AddAgentTag", addAgentTag, payload) 11 | } 12 | 13 | func addAgentTag(queue *core.Queue, option *core.Option, job core.JobAPI) { 14 | 15 | var payload = job.GetPayload() 16 | if payload == nil { 17 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 18 | return 19 | } 20 | 21 | // check payload types 22 | if reconcilePayload, ok := payload.(*core.ReconcileHostsPayload); ok { 23 | 24 | zone, targetID, err := reconcilePayload.GetSacloudServerInfo() 25 | if err != nil { 26 | queue.PushError(err) 27 | return 28 | } 29 | 30 | // sacloudから検索 31 | client := getClient(option, zone) 32 | server, err := client.Server.Read(targetID) 33 | if err != nil { 34 | queue.PushError(err) 35 | return 36 | } 37 | 38 | if !server.HasTag(option.AgentTag) { 39 | server.AppendTag(option.AgentTag) 40 | } 41 | _, err = client.Server.Update(targetID, server) 42 | if err != nil { 43 | queue.PushError(err) 44 | return 45 | } 46 | 47 | queue.PushRequest("added-agent-tag", payload) 48 | 49 | } else { 50 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [*core.ReconcileHostsPayload]", job.GetName())) 51 | return 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /job/worker/sacloud/detect_server.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/api" 5 | "github.com/sacloud/sackerel/job/core" 6 | "reflect" 7 | ) 8 | 9 | // DetectServerJob さくらのクラウド上からサーバーを検出するジョブ 10 | func DetectServerJob(payload interface{}) core.JobAPI { 11 | return core.NewJob("DetectServer", detectServer, payload) 12 | } 13 | 14 | func detectServer(queue *core.Queue, option *core.Option, job core.JobAPI) { 15 | 16 | err := doActionPerZone(option, func(client *api.Client) error { 17 | 18 | res, err := client.Server.Find() 19 | if err != nil { 20 | return err 21 | } 22 | 23 | for _, server := range res.Servers { 24 | 25 | if hasIgnoreTagWithInfoLog(server, option.IgnoreTag, queue, server.ID, server.Name, reflect.TypeOf(server)) { 26 | continue 27 | } 28 | 29 | s := server 30 | payload := core.NewCreateHostPayload(&s, client.Zone, server.ID, reflect.TypeOf(server)) 31 | if server.IsAvailable() { 32 | if server.Instance != nil && server.Instance.IsUp() { 33 | payload.MackerelHostStatus = core.MackerelHostStatusWorking 34 | } else { 35 | payload.MackerelHostStatus = core.MackerelHostStatusPowerOff 36 | } 37 | } else { 38 | payload.MackerelHostStatus = core.MackerelHostStatusMaintenance 39 | } 40 | 41 | queue.PushRequest("found-server", payload) 42 | } 43 | 44 | return nil 45 | }) 46 | 47 | if err != nil { 48 | queue.PushError(err) 49 | return 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /job/worker/mackerel/post_metrics.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/sackerel/job/core" 6 | ) 7 | 8 | // PostMetricsJob メトリクス投入用ジョブ 9 | func PostMetricsJob(payload interface{}) core.JobAPI { 10 | return core.NewJob("MackerelPostMetrics", postMetrics, payload) 11 | } 12 | 13 | func postMetrics(queue *core.Queue, option *core.Option, job core.JobAPI) { 14 | 15 | var payload = job.GetPayload() 16 | if payload == nil { 17 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 18 | return 19 | } 20 | 21 | if metricsPayload, ok := payload.(*core.CollectMetricsPayload); ok { 22 | 23 | if len(metricsPayload.MackerelMetricsParam) > 0 { 24 | client := getClient(option) 25 | err := client.PostHostMetricValues(metricsPayload.MackerelMetricsParam) 26 | 27 | if err != nil { 28 | queue.PushError(err) 29 | return 30 | } 31 | } 32 | 33 | targetName := fmt.Sprintf("(%s)", metricsPayload.SourceType.Name()) 34 | queue.PushInfo( 35 | fmt.Sprintf( 36 | "Metrics posted %-15s => SakuraID:[%d] / MackerelID:[%s] / MetricsCount:[%d]", 37 | targetName, 38 | metricsPayload.SacloudResourceID, 39 | metricsPayload.MackerelID, 40 | len(metricsPayload.MackerelMetricsParam), 41 | ), 42 | ) 43 | 44 | queue.PushRequest("posted-metrics", payload) 45 | } else { 46 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [core.CollectMetricsPayload]", job.GetName())) 47 | return 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/switch.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | ) 7 | 8 | // SwitchAPI スイッチAPI 9 | type SwitchAPI struct { 10 | *baseAPI 11 | } 12 | 13 | // NewSwitchAPI スイッチAPI作成 14 | func NewSwitchAPI(client *Client) *SwitchAPI { 15 | return &SwitchAPI{ 16 | &baseAPI{ 17 | client: client, 18 | FuncGetResourceURL: func() string { 19 | return "switch" 20 | }, 21 | }, 22 | } 23 | } 24 | 25 | // DisconnectFromBridge ブリッジとの切断 26 | func (api *SwitchAPI) DisconnectFromBridge(switchID int64) (bool, error) { 27 | var ( 28 | method = "DELETE" 29 | uri = fmt.Sprintf("%s/%d/to/bridge", api.getResourceURL(), switchID) 30 | ) 31 | return api.modify(method, uri, nil) 32 | } 33 | 34 | // ConnectToBridge ブリッジとの接続 35 | func (api *SwitchAPI) ConnectToBridge(switchID int64, bridgeID int64) (bool, error) { 36 | var ( 37 | method = "PUT" 38 | uri = fmt.Sprintf("%s/%d/to/bridge/%d", api.getResourceURL(), switchID, bridgeID) 39 | ) 40 | return api.modify(method, uri, nil) 41 | } 42 | 43 | // GetServers スイッチに接続されているサーバー一覧取得 44 | func (api *SwitchAPI) GetServers(switchID int64) ([]sacloud.Server, error) { 45 | var ( 46 | method = "GET" 47 | uri = fmt.Sprintf("%s/%d/server", api.getResourceURL(), switchID) 48 | res = &sacloud.SearchResponse{} 49 | ) 50 | err := api.baseAPI.request(method, uri, nil, res) 51 | if err != nil { 52 | return nil, err 53 | } 54 | return res.Servers, nil 55 | } 56 | -------------------------------------------------------------------------------- /job/worker/sacloud/functions.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/api" 6 | "github.com/sacloud/sackerel/job/core" 7 | "github.com/sacloud/sackerel/version" 8 | "reflect" 9 | ) 10 | 11 | func doActionPerZone(option *core.Option, sacloudAPIFunc func(*api.Client) error) error { 12 | for _, zone := range option.SakuraCloudOption.Zone { 13 | 14 | client := getClient(option, zone) 15 | // call API func per zone. 16 | err := sacloudAPIFunc(client) 17 | if err != nil { 18 | return err 19 | } 20 | } 21 | 22 | return nil 23 | } 24 | 25 | func getClient(option *core.Option, zone string) *api.Client { 26 | o := option.SakuraCloudOption 27 | 28 | client := api.NewClient(o.AccessToken, o.AccessTokenSecret, zone) 29 | client.TraceMode = o.TraceMode 30 | client.UserAgent = fmt.Sprintf("Sackerel/%s", version.Version) 31 | 32 | return client 33 | 34 | } 35 | 36 | func hasIgnoreTagWithInfoLog(target interface{}, ignoreTag string, queue *core.Queue, id int64, name string, t reflect.Type) bool { 37 | 38 | if tagsType, ok := target.(tagsHolder); ok { 39 | if tagsType.HasTag(ignoreTag) { 40 | targetName := fmt.Sprintf("(%s)", t.Name()) 41 | queue.PushInfo( 42 | fmt.Sprintf( 43 | "Ignore target %-15s => SakuraID:[%d] / Name:[%s]", 44 | targetName, 45 | id, 46 | name, 47 | ), 48 | ) 49 | return true 50 | } 51 | } 52 | 53 | return false 54 | } 55 | 56 | type tagsHolder interface { 57 | HasTag(string) bool 58 | } 59 | -------------------------------------------------------------------------------- /job/worker/sacloud/detect_database.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/api" 5 | "github.com/sacloud/sackerel/job/core" 6 | "reflect" 7 | ) 8 | 9 | // DetectDatabaseJob さくらのクラウド上からデータベースアプライアンスを検出するジョブ 10 | func DetectDatabaseJob(payload interface{}) core.JobAPI { 11 | return core.NewJob("DetectDatabase", detectDatabase, payload) 12 | } 13 | 14 | func detectDatabase(queue *core.Queue, option *core.Option, job core.JobAPI) { 15 | 16 | err := doActionPerZone(option, func(client *api.Client) error { 17 | 18 | res, err := client.Database.Find() 19 | if err != nil { 20 | return err 21 | } 22 | 23 | for _, database := range res.Databases { 24 | 25 | if hasIgnoreTagWithInfoLog(database, option.IgnoreTag, queue, database.ID, database.Name, reflect.TypeOf(database)) { 26 | continue 27 | } 28 | 29 | r := database 30 | payload := core.NewCreateHostPayload(&r, client.Zone, database.ID, reflect.TypeOf(database)) 31 | 32 | if database.IsAvailable() { 33 | if database.Instance != nil && database.Instance.IsUp() { 34 | payload.MackerelHostStatus = core.MackerelHostStatusWorking 35 | } else { 36 | payload.MackerelHostStatus = core.MackerelHostStatusPowerOff 37 | } 38 | } else { 39 | payload.MackerelHostStatus = core.MackerelHostStatusMaintenance 40 | } 41 | 42 | queue.PushRequest("found-database", payload) 43 | } 44 | 45 | return nil 46 | }) 47 | 48 | if err != nil { 49 | queue.PushError(err) 50 | return 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /job/worker/sacloud/detect_vpcrouter.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/api" 5 | "github.com/sacloud/sackerel/job/core" 6 | "reflect" 7 | ) 8 | 9 | // DetectVPCRouterJob さくらのクラウド上からVPCルーターアプライアンスを検出するジョブ 10 | func DetectVPCRouterJob(payload interface{}) core.JobAPI { 11 | return core.NewJob("DetectVPCRouter", detectVPCRouter, payload) 12 | } 13 | 14 | func detectVPCRouter(queue *core.Queue, option *core.Option, job core.JobAPI) { 15 | 16 | err := doActionPerZone(option, func(client *api.Client) error { 17 | 18 | res, err := client.VPCRouter.Find() 19 | if err != nil { 20 | return err 21 | } 22 | 23 | for _, vpcrouter := range res.VPCRouters { 24 | 25 | if hasIgnoreTagWithInfoLog(vpcrouter, option.IgnoreTag, queue, vpcrouter.ID, vpcrouter.Name, reflect.TypeOf(vpcrouter)) { 26 | continue 27 | } 28 | 29 | r := vpcrouter 30 | payload := core.NewCreateHostPayload(&r, client.Zone, vpcrouter.ID, reflect.TypeOf(vpcrouter)) 31 | if vpcrouter.IsAvailable() { 32 | if vpcrouter.Instance != nil && vpcrouter.Instance.IsUp() { 33 | payload.MackerelHostStatus = core.MackerelHostStatusWorking 34 | } else { 35 | payload.MackerelHostStatus = core.MackerelHostStatusPowerOff 36 | } 37 | } else { 38 | payload.MackerelHostStatus = core.MackerelHostStatusMaintenance 39 | } 40 | 41 | queue.PushRequest("found-vpcrouter", payload) 42 | } 43 | 44 | return nil 45 | }) 46 | 47 | if err != nil { 48 | queue.PushError(err) 49 | return 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /vendor/github.com/pmezard/go-difflib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Patrick Mezard 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | The names of its contributors may not be used to endorse or promote 14 | products derived from this software without specific prior written 15 | permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 18 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/archive.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // Archive アーカイブ 6 | type Archive struct { 7 | *Resource 8 | 9 | // Name 名称 10 | Name string 11 | // Description 説明 12 | Description string `json:",omitempty"` 13 | // Scope スコープ 14 | Scope string `json:",omitempty"` 15 | *EAvailability 16 | // SizeMB サイズ(MB単位) 17 | SizeMB int `json:",omitempty"` 18 | // MigratedMB コピー済みデータサイズ(MB単位) 19 | MigratedMB int `json:",omitempty"` 20 | // JobStatus マイグレーションジョブステータス 21 | JobStatus *MigrationJobStatus `json:",omitempty"` 22 | // OriginalArchive オリジナルアーカイブ 23 | OriginalArchive *Resource `json:",omitempty"` 24 | // ServiceClass サービスクラス 25 | ServiceClass string `json:",omitempty"` 26 | // CreatedAt 作成に一時 27 | CreatedAt *time.Time `json:",omitempty"` 28 | // Icon アイコン 29 | Icon *Icon `json:",omitempty"` 30 | // Plan プラン 31 | Plan *Resource `json:",omitempty"` 32 | // SourceDisk コピー元ディスク 33 | SourceDisk *Disk `json:",omitempty"` 34 | // SourceArchive コピー元アーカイブ 35 | SourceArchive *Archive `json:",omitempty"` 36 | // Storage ストレージ 37 | Storage *Storage `json:",omitempty"` 38 | // BundleInfo バンドル情報 39 | BundleInfo interface{} `json:",omitempty"` 40 | *TagsType 41 | } 42 | 43 | // SetSourceArchive ソースアーカイブ設定 44 | func (d *Archive) SetSourceArchive(sourceID int64) { 45 | d.SourceArchive = &Archive{ 46 | Resource: &Resource{ID: sourceID}, 47 | } 48 | } 49 | 50 | // SetSourceDisk ソースディスク設定 51 | func (d *Archive) SetSourceDisk(sourceID int64) { 52 | d.SourceDisk = &Disk{ 53 | Resource: &Resource{ID: sourceID}, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /job/worker/sacloud/detect_loadbalancer.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/api" 5 | "github.com/sacloud/sackerel/job/core" 6 | "reflect" 7 | ) 8 | 9 | // DetectLoadBalancerJob さくらのクラウド上からロードバランサーアプライアンスを検出するジョブ 10 | func DetectLoadBalancerJob(payload interface{}) core.JobAPI { 11 | return core.NewJob("DetectLoadBalancer", detectLoadBalancer, payload) 12 | } 13 | 14 | func detectLoadBalancer(queue *core.Queue, option *core.Option, job core.JobAPI) { 15 | 16 | err := doActionPerZone(option, func(client *api.Client) error { 17 | 18 | res, err := client.LoadBalancer.Find() 19 | if err != nil { 20 | return err 21 | } 22 | 23 | for _, loadbalancer := range res.LoadBalancers { 24 | 25 | if hasIgnoreTagWithInfoLog(loadbalancer, option.IgnoreTag, queue, loadbalancer.ID, loadbalancer.Name, reflect.TypeOf(loadbalancer)) { 26 | continue 27 | } 28 | 29 | s := loadbalancer 30 | payload := core.NewCreateHostPayload(&s, client.Zone, loadbalancer.ID, reflect.TypeOf(loadbalancer)) 31 | 32 | if loadbalancer.IsAvailable() { 33 | if loadbalancer.Instance != nil && loadbalancer.Instance.IsUp() { 34 | payload.MackerelHostStatus = core.MackerelHostStatusWorking 35 | } else { 36 | payload.MackerelHostStatus = core.MackerelHostStatusPowerOff 37 | } 38 | } else { 39 | payload.MackerelHostStatus = core.MackerelHostStatusMaintenance 40 | } 41 | 42 | queue.PushRequest("found-loadbalancer", payload) 43 | } 44 | 45 | return nil 46 | }) 47 | 48 | if err != nil { 49 | queue.PushError(err) 50 | return 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/doc.go: -------------------------------------------------------------------------------- 1 | // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. 2 | // 3 | // Example Usage 4 | // 5 | // The following is a complete example using assert in a standard test function: 6 | // import ( 7 | // "testing" 8 | // "github.com/stretchr/testify/assert" 9 | // ) 10 | // 11 | // func TestSomething(t *testing.T) { 12 | // 13 | // var a string = "Hello" 14 | // var b string = "Hello" 15 | // 16 | // assert.Equal(t, a, b, "The two words should be the same.") 17 | // 18 | // } 19 | // 20 | // if you assert many times, use the format below: 21 | // 22 | // import ( 23 | // "testing" 24 | // "github.com/stretchr/testify/assert" 25 | // ) 26 | // 27 | // func TestSomething(t *testing.T) { 28 | // assert := assert.New(t) 29 | // 30 | // var a string = "Hello" 31 | // var b string = "Hello" 32 | // 33 | // assert.Equal(a, b, "The two words should be the same.") 34 | // } 35 | // 36 | // Assertions 37 | // 38 | // Assertions allow you to easily write test code, and are global funcs in the `assert` package. 39 | // All assertion functions take, as the first argument, the `*testing.T` object provided by the 40 | // testing framework. This allows the assertion funcs to write the failings and other details to 41 | // the correct place. 42 | // 43 | // Every assertion function also takes an optional string message as the final argument, 44 | // allowing custom error messages to be appended to the message the assertion method outputs. 45 | package assert 46 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TEST?=$$(go list ./... | grep -v vendor) 2 | VETARGS?=-all 3 | GOFMT_FILES?=$$(find . -name '*.go' | grep -v vendor) 4 | 5 | default: test vet 6 | 7 | run: 8 | go run $(CURDIR)/main.go --disable-healthcheck $(ARGS) 9 | 10 | clean: 11 | rm -Rf $(CURDIR)/bin/* 12 | 13 | build: clean vet 14 | govendor build -ldflags "-s -w -X `go list ./version`.Revision=`git rev-parse --short HEAD 2>/dev/null`" -o $(CURDIR)/bin/sackerel $(CURDIR)/main.go 15 | 16 | build-x: clean vet 17 | sh -c "'$(CURDIR)/scripts/build.sh'" 18 | 19 | test: vet 20 | govendor test $(TEST) $(TESTARGS) -v -timeout=30m -parallel=4 ; 21 | 22 | vet: fmt 23 | @echo "go tool vet $(VETARGS) ." 24 | @go tool vet $(VETARGS) $$(ls -d */ | grep -v vendor) ; if [ $$? -eq 1 ]; then \ 25 | echo ""; \ 26 | echo "Vet found suspicious constructs. Please check the reported constructs"; \ 27 | echo "and fix them if necessary before submitting the code for review."; \ 28 | exit 1; \ 29 | fi 30 | 31 | fmt: 32 | gofmt -s -l -w $(GOFMT_FILES) 33 | 34 | docker-run: 35 | sh -c "'$(CURDIR)/scripts/build_docker_image.sh'" ; \ 36 | sh -c "'$(CURDIR)/scripts/run_on_docker.sh'" 37 | 38 | docker-daemon: 39 | sh -c "'$(CURDIR)/scripts/build_docker_image.sh'" ; \ 40 | sh -c "'$(CURDIR)/scripts/run_on_docker_daemon.sh'" 41 | 42 | docker-logs: 43 | docker logs -f sackerel 44 | 45 | docker-rm: 46 | docker rm -f sackerel 47 | 48 | docker-test: 49 | sh -c "'$(CURDIR)/scripts/build_on_docker.sh' 'test'" 50 | 51 | docker-build: clean 52 | sh -c "'$(CURDIR)/scripts/build_on_docker.sh' 'build-x'" 53 | 54 | 55 | .PHONY: default test vet fmt lint 56 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_base_test.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "github.com/sacloud/sackerel/job/core" 5 | "github.com/stretchr/testify/assert" 6 | "reflect" 7 | "testing" 8 | "time" 9 | ) 10 | 11 | var queue = core.NewQueue(5, 5, 5, 5) 12 | var option = core.NewOption() 13 | var jobCheckFunc = func(t *testing.T, q *core.Queue, f func(v core.JobRequestAPI), w func(err error), e func(err error)) { 14 | for { 15 | select { 16 | case v := <-q.Request: 17 | if f != nil { 18 | f(v) 19 | } 20 | return 21 | case v := <-q.Logs.Warn: 22 | if w != nil { 23 | w(v) 24 | } 25 | return 26 | case v := <-q.Logs.Error: 27 | if e != nil { 28 | e(v) 29 | } 30 | return 31 | case <-time.After(5 * time.Second): 32 | assert.Fail(t, "Timeout") 33 | return 34 | } 35 | } 36 | } 37 | 38 | func baseExchangeJobTest(t *testing.T) bool { 39 | var job core.JobAPI 40 | // PayloadがnilだとWarn 41 | job = DatabaseJob(nil) 42 | go job.Start(queue, option) 43 | 44 | jobCheckFunc(t, queue, nil, func(err error) { 45 | assert.Error(t, err) 46 | }, nil) 47 | 48 | // PayloadにCreateHostPayload以外を渡すとWarn 49 | job = DatabaseJob("test") 50 | go job.Start(queue, option) 51 | jobCheckFunc(t, queue, nil, func(err error) { 52 | assert.Error(t, err) 53 | }, nil) 54 | 55 | // ソースに必要な型が設定されていなければエラー 56 | payload := core.NewCreateHostPayload("test", "is1b", 0, reflect.TypeOf("test")) 57 | job = DatabaseJob(payload) 58 | go job.Start(queue, option) 59 | jobCheckFunc(t, queue, nil, func(err error) { 60 | assert.Error(t, err) 61 | }, nil) 62 | 63 | return true 64 | } 65 | -------------------------------------------------------------------------------- /job/worker/sacloud/sacloud_test.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "github.com/sacloud/sackerel/job/core" 5 | "log" 6 | "os" 7 | "testing" 8 | ) 9 | 10 | var testSetupHandlers []func() 11 | var testTearDownHandlers []func() 12 | var mockOption *core.Option 13 | var mockBlockQueue *core.Queue 14 | 15 | func TestMain(m *testing.M) { 16 | //環境変数にトークン/シークレットがある場合のみテスト実施 17 | accessToken := os.Getenv("SAKURACLOUD_ACCESS_TOKEN") 18 | accessTokenSecret := os.Getenv("SAKURACLOUD_ACCESS_TOKEN_SECRET") 19 | 20 | if accessToken == "" || accessTokenSecret == "" { 21 | log.Println("Please Set ENV 'SAKURACLOUD_ACCESS_TOKEN' and 'SAKURACLOUD_ACCESS_TOKEN_SECRET'") 22 | os.Exit(0) // exit normal 23 | } 24 | 25 | // setup mock option 26 | mockOption = core.NewOption() 27 | mockOption.SakuraCloudOption.AccessToken = accessToken 28 | mockOption.SakuraCloudOption.AccessTokenSecret = accessTokenSecret 29 | 30 | // setup mock queue 31 | mockBlockQueue = core.NewQueue(1, 1, 1, 1) 32 | 33 | // setup test 34 | for _, f := range testSetupHandlers { 35 | f() 36 | } 37 | 38 | ret := m.Run() 39 | 40 | // teardown 41 | for _, f := range testTearDownHandlers { 42 | f() 43 | } 44 | 45 | os.Exit(ret) 46 | } 47 | 48 | func TestDetectServer(t *testing.T) { 49 | 50 | //work := NewDetectServerWork(mockOption.SakuraCloudOption).(*DetectServerWork) 51 | // 52 | //assert.NotNil(t, work) 53 | // 54 | //go work.detect(mockBlockQueue) 55 | // 56 | //select { 57 | //case w := <-mockBlockQueue.WorkRequest: 58 | // name := w.GetName() 59 | // assert.Equal(t, name, "found-server") 60 | // //payload := w.GetPayload() 61 | // //assert.NotNil(t, payload) 62 | // 63 | //case <-time.After(1 * time.Minute): 64 | // assert.Fail(t, "Timeout [%s]", "detect") 65 | //} 66 | 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/product_server.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | "strconv" 7 | ) 8 | 9 | // ProductServerAPI サーバープランAPI 10 | type ProductServerAPI struct { 11 | *baseAPI 12 | } 13 | 14 | // NewProductServerAPI サーバープランAPI作成 15 | func NewProductServerAPI(client *Client) *ProductServerAPI { 16 | return &ProductServerAPI{ 17 | &baseAPI{ 18 | client: client, 19 | // FuncGetResourceURL 20 | FuncGetResourceURL: func() string { 21 | return "product/server" 22 | }, 23 | }, 24 | } 25 | } 26 | 27 | func (api *ProductServerAPI) getPlanIDBySpec(core int, memGB int) (int64, error) { 28 | //assert args 29 | if core <= 0 { 30 | return -1, fmt.Errorf("Invalid Parameter: CPU Core") 31 | } 32 | if memGB <= 0 { 33 | return -1, fmt.Errorf("Invalid Parameter: Memory Size(GB)") 34 | } 35 | 36 | return strconv.ParseInt(fmt.Sprintf("%d%03d", memGB, core), 10, 64) 37 | } 38 | 39 | // IsValidPlan 指定のコア数/メモリサイズのプランが存在し、有効であるか判定 40 | func (api *ProductServerAPI) IsValidPlan(core int, memGB int) (bool, error) { 41 | 42 | planID, err := api.getPlanIDBySpec(core, memGB) 43 | if err != nil { 44 | return false, err 45 | } 46 | productServer, err := api.Read(planID) 47 | 48 | if err != nil { 49 | return false, err 50 | } 51 | 52 | if productServer != nil { 53 | return true, nil 54 | } 55 | 56 | return false, fmt.Errorf("Server Plan[%d] Not Found", planID) 57 | 58 | } 59 | 60 | // GetBySpec 指定のコア数/メモリサイズのサーバープランを取得 61 | func (api *ProductServerAPI) GetBySpec(core int, memGB int) (*sacloud.ProductServer, error) { 62 | planID, err := api.getPlanIDBySpec(core, memGB) 63 | 64 | productServer, err := api.Read(planID) 65 | 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | return productServer, nil 71 | } 72 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/instance.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // Instance インスタンス 6 | type Instance struct { 7 | // Server サーバー 8 | Server Resource `json:",omitempty"` 9 | *EServerInstanceStatus 10 | // StatusChangedAt ステータス変更日時 11 | StatusChangedAt *time.Time `json:",omitempty"` 12 | // MigrationProgress コピージョブ進捗状態 13 | MigrationProgress string `json:",omitempty"` 14 | // MigrationSchedule コピージョブスケジュール 15 | MigrationSchedule string `json:",omitempty"` 16 | // IsMigrating コピージョブ実施中フラグ 17 | IsMigrating bool `json:",omitempty"` 18 | // MigrationAllowed コピージョブ許可 19 | MigrationAllowed string `json:",omitempty"` 20 | // ModifiedAt 変更日時 21 | ModifiedAt *time.Time `json:",omitempty"` 22 | // Host 23 | Host struct { 24 | // Name ホスト名 25 | Name string `json:",omitempty"` 26 | // InfoURL インフォURL 27 | InfoURL string `json:",omitempty"` 28 | // Class クラス 29 | Class string `json:",omitempty"` 30 | // Version バージョン 31 | Version int `json:",omitempty"` 32 | // SystemVersion システムバージョン 33 | SystemVersion string `json:",omitempty"` 34 | } `json:",omitempty"` 35 | // CDROM ISOイメージ 36 | CDROM *CDROM `json:",omitempty"` 37 | // CDROMStorage ISOイメージストレージ 38 | CDROMStorage *Storage `json:",omitempty"` 39 | } 40 | 41 | // Storage ストレージ 42 | type Storage struct { 43 | *Resource 44 | // Class クラス 45 | Class string `json:",omitempty"` 46 | // Name 名称 47 | Name string `json:",omitempty"` 48 | // Description 説明 49 | Description string `json:",omitempty"` 50 | // Zone ゾーン 51 | Zone *Zone `json:",omitempty"` 52 | // DiskPlan ディスクプラン 53 | DiskPlan struct { 54 | *Resource 55 | // StorageClass ストレージクラス 56 | StorageClass string `json:",omitempty"` 57 | // Name 名称 58 | Name string `json:",omitempty"` 59 | } `json:",omitempty"` 60 | //Capacity []string `json:",omitempty"` 61 | } 62 | -------------------------------------------------------------------------------- /job/worker/mackerel/regist_target.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | "github.com/sacloud/sackerel/job/core" 5 | ) 6 | 7 | // RegistServerJob Mackerelホストとしてサーバーを登録するジョブ 8 | func RegistServerJob(payload interface{}) core.JobAPI { 9 | return core.NewJob("MackerelRegistServer", registServer, payload) 10 | } 11 | 12 | // RegistRouterJob Mackerelホストとしてルーターを登録するジョブ 13 | func RegistRouterJob(payload interface{}) core.JobAPI { 14 | return core.NewJob("MackerelRegistRouter", registRouter, payload) 15 | } 16 | 17 | // RegistLoadBalancerJob Mackerelホストとしてロードバランサーを登録するジョブ 18 | func RegistLoadBalancerJob(payload interface{}) core.JobAPI { 19 | return core.NewJob("MackerelRegistLoadBalancer", registLoadBalancer, payload) 20 | } 21 | 22 | // RegistVPCRouterJob MackerelホストとしてVPCルーターを登録するジョブ 23 | func RegistVPCRouterJob(payload interface{}) core.JobAPI { 24 | return core.NewJob("MackerelRegistVPCRouter", registVPCRouter, payload) 25 | } 26 | 27 | // RegistDatabaseJob Mackerelホストとしてデータベースを登録するジョブ 28 | func RegistDatabaseJob(payload interface{}) core.JobAPI { 29 | return core.NewJob("MackerelRegistDatabase", registDatabase, payload) 30 | } 31 | 32 | func registServer(queue *core.Queue, option *core.Option, job core.JobAPI) { 33 | registMackerelTarget(queue, option, job, "server") 34 | } 35 | func registRouter(queue *core.Queue, option *core.Option, job core.JobAPI) { 36 | registMackerelTarget(queue, option, job, "router") 37 | } 38 | func registLoadBalancer(queue *core.Queue, option *core.Option, job core.JobAPI) { 39 | registMackerelTarget(queue, option, job, "loadbalancer") 40 | } 41 | func registVPCRouter(queue *core.Queue, option *core.Option, job core.JobAPI) { 42 | registMackerelTarget(queue, option, job, "vpcrouter") 43 | } 44 | func registDatabase(queue *core.Queue, option *core.Option, job core.JobAPI) { 45 | registMackerelTarget(queue, option, job, "database") 46 | } 47 | -------------------------------------------------------------------------------- /job/worker/mackerel/find_target.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | "github.com/sacloud/sackerel/job/core" 5 | ) 6 | 7 | // FindServerJob Mackerel上のホストからサーバーを検索するジョブ 8 | func FindServerJob(payload interface{}) core.JobAPI { 9 | return core.NewJob("MackerelFindServer", findMackerelServer, payload) 10 | } 11 | 12 | // FindRouterJob Mackerel上のホストからルーターを検索するジョブ 13 | func FindRouterJob(payload interface{}) core.JobAPI { 14 | return core.NewJob("MackerelFindRouter", findMackerelRouter, payload) 15 | } 16 | 17 | // FindLoadBalancerJob Mackerel上のホストからロードバランサーを検索するジョブ 18 | func FindLoadBalancerJob(payload interface{}) core.JobAPI { 19 | return core.NewJob("MackerelFindLoadBalancer", findMackerelLoadBalancer, payload) 20 | } 21 | 22 | // FindVPCRouterJob Mackerel上のホストからVPCルーターを検索するジョブ 23 | func FindVPCRouterJob(payload interface{}) core.JobAPI { 24 | return core.NewJob("MackerelFindVPCRouter", findMackerelVPCRouter, payload) 25 | } 26 | 27 | // FindDatabaseJob Mackerel上のホストからデータベースを検索するジョブ 28 | func FindDatabaseJob(payload interface{}) core.JobAPI { 29 | return core.NewJob("MackerelFindDatabase", findMackerelDatabase, payload) 30 | } 31 | 32 | func findMackerelServer(queue *core.Queue, option *core.Option, job core.JobAPI) { 33 | findMackerelTarget(queue, option, job, "server") 34 | } 35 | func findMackerelRouter(queue *core.Queue, option *core.Option, job core.JobAPI) { 36 | findMackerelTarget(queue, option, job, "router") 37 | } 38 | func findMackerelLoadBalancer(queue *core.Queue, option *core.Option, job core.JobAPI) { 39 | findMackerelTarget(queue, option, job, "loadbalancer") 40 | } 41 | func findMackerelVPCRouter(queue *core.Queue, option *core.Option, job core.JobAPI) { 42 | findMackerelTarget(queue, option, job, "vpcrouter") 43 | } 44 | func findMackerelDatabase(queue *core.Queue, option *core.Option, job core.JobAPI) { 45 | findMackerelTarget(queue, option, job, "database") 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/bypasssafe.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Dave Collins 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // NOTE: Due to the following build constraints, this file will only be compiled 16 | // when the code is running on Google App Engine, compiled by GopherJS, or 17 | // "-tags safe" is added to the go build command line. The "disableunsafe" 18 | // tag is deprecated and thus should not be used. 19 | // +build js appengine safe disableunsafe 20 | 21 | package spew 22 | 23 | import "reflect" 24 | 25 | const ( 26 | // UnsafeDisabled is a build-time constant which specifies whether or 27 | // not access to the unsafe package is available. 28 | UnsafeDisabled = true 29 | ) 30 | 31 | // unsafeReflectValue typically converts the passed reflect.Value into a one 32 | // that bypasses the typical safety restrictions preventing access to 33 | // unaddressable and unexported data. However, doing this relies on access to 34 | // the unsafe package. This is a stub version which simply returns the passed 35 | // reflect.Value when the unsafe package is not available. 36 | func unsafeReflectValue(v reflect.Value) reflect.Value { 37 | return v 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/cdrom.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | "time" 7 | ) 8 | 9 | // CDROMAPI ISOイメージAPI 10 | type CDROMAPI struct { 11 | *baseAPI 12 | } 13 | 14 | // NewCDROMAPI ISOイメージAPI新規作成 15 | func NewCDROMAPI(client *Client) *CDROMAPI { 16 | return &CDROMAPI{ 17 | &baseAPI{ 18 | client: client, 19 | FuncGetResourceURL: func() string { 20 | return "cdrom" 21 | }, 22 | }, 23 | } 24 | } 25 | 26 | // Create 新規作成 27 | func (api *CDROMAPI) Create(value *sacloud.CDROM) (*sacloud.CDROM, *sacloud.FTPServer, error) { 28 | f := func(res *sacloud.Response) error { 29 | return api.create(api.createRequest(value), res) 30 | } 31 | res := &sacloud.Response{} 32 | err := f(res) 33 | if err != nil { 34 | return nil, nil, err 35 | } 36 | return res.CDROM, res.FTPServer, nil 37 | } 38 | 39 | // OpenFTP FTP接続開始 40 | func (api *CDROMAPI) OpenFTP(id int64, reset bool) (*sacloud.FTPServer, error) { 41 | var ( 42 | method = "PUT" 43 | uri = fmt.Sprintf("%s/%d/ftp", api.getResourceURL(), id) 44 | body = map[string]bool{"ChangePassword": reset} 45 | res = &sacloud.Response{} 46 | ) 47 | 48 | result, err := api.action(method, uri, body, res) 49 | if !result || err != nil { 50 | return nil, err 51 | } 52 | 53 | return res.FTPServer, nil 54 | } 55 | 56 | // CloseFTP FTP接続終了 57 | func (api *CDROMAPI) CloseFTP(id int64) (bool, error) { 58 | var ( 59 | method = "DELETE" 60 | uri = fmt.Sprintf("%s/%d/ftp", api.getResourceURL(), id) 61 | ) 62 | return api.modify(method, uri, nil) 63 | 64 | } 65 | 66 | // SleepWhileCopying コピー終了まで待機 67 | func (api *CDROMAPI) SleepWhileCopying(id int64, timeout time.Duration) error { 68 | 69 | current := 0 * time.Second 70 | interval := 5 * time.Second 71 | for { 72 | archive, err := api.Read(id) 73 | if err != nil { 74 | return err 75 | } 76 | 77 | if archive.IsAvailable() { 78 | return nil 79 | } 80 | time.Sleep(interval) 81 | current += interval 82 | 83 | if timeout > 0 && current > timeout { 84 | return fmt.Errorf("Timeout: SleepWhileCopying[disk:%d]", id) 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_loadbalancer_test.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/sacloud" 5 | "github.com/sacloud/sackerel/job/core" 6 | "github.com/stretchr/testify/assert" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | var loadbalancer = &sacloud.LoadBalancer{ 12 | Appliance: &sacloud.Appliance{ 13 | Resource: &sacloud.Resource{ID: 123456789012}, 14 | Name: "Test", 15 | TagsType: &sacloud.TagsType{ 16 | Tags: []string{"tag1", "tag2"}, 17 | }, 18 | }, 19 | Remark: &sacloud.LoadBalancerRemark{ 20 | ApplianceRemarkBase: &sacloud.ApplianceRemarkBase{ 21 | Servers: []interface{}{ 22 | map[string]interface{}{ 23 | "IPAddress": "192.168.0.1", 24 | }, 25 | map[string]interface{}{ 26 | "IPAddress": "192.168.0.2", 27 | }, 28 | }, 29 | }, 30 | }, 31 | } 32 | 33 | func TestLoadBalancerJob(t *testing.T) { 34 | if !baseExchangeJobTest(t) { 35 | return 36 | } 37 | 38 | lbPayload := core.NewCreateHostPayload(loadbalancer, "is1b", 123456789012, reflect.TypeOf(loadbalancer)) 39 | job := LoadBalancerJob(lbPayload) 40 | errFunc := func(err error) { 41 | assert.Fail(t, "Warn or Error log printed") 42 | } 43 | go job.Start(queue, option) 44 | jobCheckFunc(t, queue, func(v core.JobRequestAPI) { 45 | payload := v.GetPayload().(*core.CreateHostPayload) 46 | assert.NotNil(t, payload) 47 | 48 | para := payload.MackerelHostParam 49 | assert.NotNil(t, para) 50 | 51 | assert.Equal(t, para.CustomIdentifier, payload.GenerateMackerelName()) 52 | assert.Equal(t, para.DisplayName, "Test") 53 | assert.Equal(t, para.Name, payload.GenerateMackerelName()) 54 | assert.Equal(t, para.RoleFullnames, []string{ 55 | "SakuraCloud:LoadBalancer", 56 | "SakuraCloud:Zone-is1b", 57 | "SakuraCloud:tag1", 58 | "SakuraCloud:tag2", 59 | }) 60 | assert.Equal(t, para.Interfaces[0].Name, "eth0") 61 | assert.Equal(t, para.Interfaces[0].IPAddress, "192.168.0.1") 62 | assert.Equal(t, para.Interfaces[0].MacAddress, "") 63 | 64 | assert.Equal(t, para.Interfaces[1].Name, "eth1") 65 | assert.Equal(t, para.Interfaces[1].IPAddress, "192.168.0.2") 66 | assert.Equal(t, para.Interfaces[1].MacAddress, "") 67 | 68 | }, errFunc, errFunc) 69 | 70 | } 71 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/appliance.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import "time" 4 | 5 | // Appliance アプライアンス基底クラス 6 | type Appliance struct { 7 | *Resource 8 | // Class リソースクラス 9 | Class string `json:",omitempty"` 10 | // Name 名称 11 | Name string `json:",omitempty"` 12 | // Description 説明 13 | Description string `json:",omitempty"` 14 | // Plan プラン 15 | Plan *Resource 16 | 17 | //Settings 18 | 19 | // SettingHash 設定ハッシュ値 20 | SettingHash string `json:",omitempty"` 21 | 22 | //Remark *ApplianceRemark `json:",omitempty"` 23 | 24 | *EAvailability 25 | // Instance インスタンス 26 | Instance *EServerInstanceStatus `json:",omitempty"` 27 | // ServiceClass サービスクラス 28 | ServiceClass string `json:",omitempty"` 29 | // CreatedAt 作成日時 30 | CreatedAt *time.Time `json:",omitempty"` 31 | // Icon アイコン 32 | Icon *Icon `json:",omitempty"` 33 | // Switch スイッチ 34 | Switch *Switch `json:",omitempty"` 35 | // Interfaces インターフェース 36 | Interfaces []Interface `json:",omitempty"` 37 | 38 | *TagsType 39 | } 40 | 41 | //HACK Appliance:Zone.IDがRoute/LoadBalancerの場合でデータ型が異なるため 42 | //それぞれのstruct定義でZoneだけ上書きした構造体を定義して使う 43 | 44 | // ApplianceRemarkBase アプライアンス Remark 基底クラス 45 | type ApplianceRemarkBase struct { 46 | // Servers 配下のサーバー群 47 | Servers []interface{} 48 | // Switch 接続先スイッチ 49 | Switch *ApplianceRemarkSwitch `json:",omitempty"` 50 | //Zone *Resource `json:",omitempty"` 51 | 52 | // VRRP VRRP 53 | VRRP *ApplianceRemarkVRRP `json:",omitempty"` 54 | // Network ネットワーク 55 | Network *ApplianceRemarkNetwork `json:",omitempty"` 56 | 57 | //Plan *Resource 58 | } 59 | 60 | //type ApplianceServer struct { 61 | // IPAddress string `json:",omitempty"` 62 | //} 63 | 64 | // ApplianceRemarkSwitch スイッチ 65 | type ApplianceRemarkSwitch struct { 66 | // ID リソースID 67 | ID string `json:",omitempty"` 68 | // Scope スコープ 69 | Scope string `json:",omitempty"` 70 | } 71 | 72 | // ApplianceRemarkVRRP VRRP 73 | type ApplianceRemarkVRRP struct { 74 | // VRID VRID 75 | VRID int `json:",omitempty"` 76 | } 77 | 78 | // ApplianceRemarkNetwork ネットワーク 79 | type ApplianceRemarkNetwork struct { 80 | // NetworkMaskLen ネットワークマスク長 81 | NetworkMaskLen int `json:",omitempty"` 82 | // DefaultRoute デフォルトルート 83 | DefaultRoute string `json:",omitempty"` 84 | } 85 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_server_test.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/sacloud" 5 | "github.com/sacloud/sackerel/job/core" 6 | "github.com/stretchr/testify/assert" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | var server = &sacloud.Server{ 12 | Resource: &sacloud.Resource{ID: 123456789012}, 13 | Name: "Test", 14 | TagsType: &sacloud.TagsType{ 15 | Tags: []string{"tag1", "tag2"}, 16 | }, 17 | Interfaces: []sacloud.Interface{ 18 | { 19 | IPAddress: "192.168.0.1", 20 | MACAddress: "00:00::00:00:00:00:01", 21 | Switch: &sacloud.Switch{ 22 | Scope: sacloud.ESCopeShared, //共有セグメント 23 | }, 24 | }, 25 | { 26 | UserIPAddress: "192.168.0.2", 27 | MACAddress: "00:00::00:00:00:00:02", 28 | Switch: &sacloud.Switch{ 29 | Scope: sacloud.ESCopeUser, // スイッチ 30 | }, 31 | }, 32 | }, 33 | } 34 | 35 | func TestServerJob(t *testing.T) { 36 | if !baseExchangeJobTest(t) { 37 | return 38 | } 39 | 40 | serverPayload := core.NewCreateHostPayload(server, "is1b", 123456789012, reflect.TypeOf(server)) 41 | job := ServerJob(serverPayload) 42 | errFunc := func(err error) { 43 | assert.Fail(t, "Warn or Error log printed") 44 | } 45 | go job.Start(queue, option) 46 | jobCheckFunc(t, queue, func(v core.JobRequestAPI) { 47 | payload := v.GetPayload().(*core.CreateHostPayload) 48 | assert.NotNil(t, payload) 49 | 50 | para := payload.MackerelHostParam 51 | assert.NotNil(t, para) 52 | 53 | assert.Equal(t, para.CustomIdentifier, payload.GenerateMackerelName()) 54 | assert.Equal(t, para.DisplayName, "Test") 55 | assert.Equal(t, para.Name, payload.GenerateMackerelName()) 56 | assert.Equal(t, para.RoleFullnames, []string{ 57 | "SakuraCloud:Server", 58 | "SakuraCloud:Zone-is1b", 59 | "SakuraCloud:tag1", 60 | "SakuraCloud:tag2", 61 | }) 62 | assert.Equal(t, para.Interfaces[0].Name, "eth0") 63 | assert.Equal(t, para.Interfaces[0].IPAddress, "192.168.0.1") 64 | assert.Equal(t, para.Interfaces[0].MacAddress, "00:00::00:00:00:00:01") 65 | 66 | assert.Equal(t, para.Interfaces[1].Name, "eth1") 67 | assert.Equal(t, para.Interfaces[1].IPAddress, "192.168.0.2") 68 | assert.Equal(t, para.Interfaces[1].MacAddress, "00:00::00:00:00:00:02") 69 | 70 | }, errFunc, errFunc) 71 | } 72 | -------------------------------------------------------------------------------- /vendor/github.com/mackerelio/mackerel-client-go/alerts.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | ) 8 | 9 | /* 10 | { 11 | "alerts": [ 12 | { 13 | "id": "2wpLU5fBXbG", 14 | "status": "CRITICAL", 15 | "monitorId": "2cYjfibBkaj", 16 | "type": "connectivity", 17 | "openedAt": 1445399342, 18 | "hostId": "2vJ965ygiXf" 19 | }, 20 | { 21 | "id": "2ust8jNxFH3", 22 | "status": "CRITICAL", 23 | "monitorId": "2cYjfibBkaj", 24 | "type": "connectivity", 25 | "openedAt": 1441939801, 26 | "hostId": "2tFrtykgMib" 27 | } 28 | ] 29 | } 30 | */ 31 | 32 | // Alert information 33 | type Alert struct { 34 | ID string `json:"id,omitempty"` 35 | Status string `json:"status,omitempty"` 36 | MonitorID string `json:"monitorId,omitempty"` 37 | Type string `json:"type,omitempty"` 38 | HostID string `json:"hostId,omitempty"` 39 | Value float64 `json:"value,omitempty"` 40 | Message string `json:"message,omitempty"` 41 | Reason string `json:"reason,omitempty"` 42 | OpenedAt int64 `json:"openedAt,omitempty"` 43 | ClosedAt int64 `json:"closedAt,omitempty"` 44 | } 45 | 46 | // FindAlerts find alerts 47 | func (c *Client) FindAlerts() ([]*Alert, error) { 48 | req, err := http.NewRequest("GET", c.urlFor("/api/v0/alerts").String(), nil) 49 | if err != nil { 50 | return nil, err 51 | } 52 | resp, err := c.Request(req) 53 | defer closeResponse(resp) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | var data struct { 59 | Alerts []*(Alert) `json:"alerts"` 60 | } 61 | err = json.NewDecoder(resp.Body).Decode(&data) 62 | if err != nil { 63 | return nil, err 64 | } 65 | return data.Alerts, err 66 | } 67 | 68 | // CloseAlert close alert 69 | func (c *Client) CloseAlert(alertID string, reason string) (*Alert, error) { 70 | var reqBody struct { 71 | Reason string `json:"reason"` 72 | } 73 | reqBody.Reason = reason 74 | resp, err := c.PostJSON(fmt.Sprintf("/api/v0/alerts/%s/close", alertID), &reqBody) 75 | defer closeResponse(resp) 76 | if err != nil { 77 | return nil, err 78 | } 79 | 80 | var data *Alert 81 | err = json.NewDecoder(resp.Body).Decode(&data) 82 | if err != nil { 83 | return nil, err 84 | } 85 | 86 | return data, nil 87 | } 88 | -------------------------------------------------------------------------------- /vendor/gopkg.in/urfave/cli.v2/category.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | type CommandCategories interface { 4 | // AddCommand adds a command to a category, creating a new category if necessary. 5 | AddCommand(category string, command *Command) 6 | // Categories returns a copy of the category slice 7 | Categories() []CommandCategory 8 | } 9 | 10 | type commandCategories []*commandCategory 11 | 12 | func newCommandCategories() CommandCategories { 13 | ret := commandCategories([]*commandCategory{}) 14 | return &ret 15 | } 16 | 17 | func (c *commandCategories) Less(i, j int) bool { 18 | return (*c)[i].Name() < (*c)[j].Name() 19 | } 20 | 21 | func (c *commandCategories) Len() int { 22 | return len(*c) 23 | } 24 | 25 | func (c *commandCategories) Swap(i, j int) { 26 | (*c)[i], (*c)[j] = (*c)[j], (*c)[i] 27 | } 28 | 29 | func (c *commandCategories) AddCommand(category string, command *Command) { 30 | for _, commandCategory := range []*commandCategory(*c) { 31 | if commandCategory.name == category { 32 | commandCategory.commands = append(commandCategory.commands, command) 33 | return 34 | } 35 | } 36 | newVal := commandCategories(append(*c, 37 | &commandCategory{name: category, commands: []*Command{command}})) 38 | (*c) = newVal 39 | } 40 | 41 | func (c *commandCategories) Categories() []CommandCategory { 42 | ret := make([]CommandCategory, len(*c)) 43 | for i, cat := range *c { 44 | ret[i] = cat 45 | } 46 | return ret 47 | } 48 | 49 | // CommandCategory is a category containing commands. 50 | type CommandCategory interface { 51 | // Name returns the category name string 52 | Name() string 53 | // VisibleCommands returns a slice of the Commands with Hidden=false 54 | VisibleCommands() []*Command 55 | } 56 | 57 | type commandCategory struct { 58 | name string 59 | commands []*Command 60 | } 61 | 62 | func newCommandCategory(name string) *commandCategory { 63 | return &commandCategory{ 64 | name: name, 65 | commands: []*Command{}, 66 | } 67 | } 68 | 69 | func (c *commandCategory) Name() string { 70 | return c.name 71 | } 72 | 73 | func (c *commandCategory) VisibleCommands() []*Command { 74 | if c.commands == nil { 75 | c.commands = []*Command{} 76 | } 77 | 78 | ret := []*Command{} 79 | for _, command := range c.commands { 80 | if !command.Hidden { 81 | ret = append(ret, command) 82 | } 83 | } 84 | return ret 85 | } 86 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_router_test.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/sacloud" 5 | "github.com/sacloud/sackerel/job/core" 6 | "github.com/stretchr/testify/assert" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | var router = &sacloud.Internet{ 12 | Resource: &sacloud.Resource{ID: 123456789012}, 13 | Name: "Test", 14 | TagsType: &sacloud.TagsType{ 15 | Tags: []string{"tag1", "tag2"}, 16 | }, 17 | Switch: &sacloud.Switch{ 18 | TagsType: &sacloud.TagsType{ 19 | Tags: []string{"tag1", "tag2"}, 20 | }, 21 | Subnets: []sacloud.SwitchSubnet{ 22 | { 23 | IPAddresses: struct { 24 | Min string `json:",omitempty"` 25 | Max string `json:",omitempty"` 26 | }{ 27 | Min: "192.168.0.1", 28 | Max: "192.168.0.3", 29 | }, 30 | }, 31 | }, 32 | }, 33 | } 34 | 35 | func TestRouterJob(t *testing.T) { 36 | if !baseExchangeJobTest(t) { 37 | return 38 | } 39 | 40 | routerPayload := core.NewCreateHostPayload(router, "is1b", 123456789012, reflect.TypeOf(router)) 41 | job := RouterJob(routerPayload) 42 | errFunc := func(err error) { 43 | assert.Fail(t, "Warn or Error log printed") 44 | } 45 | go job.Start(queue, option) 46 | jobCheckFunc(t, queue, func(v core.JobRequestAPI) { 47 | payload := v.GetPayload().(*core.CreateHostPayload) 48 | assert.NotNil(t, payload) 49 | 50 | para := payload.MackerelHostParam 51 | assert.NotNil(t, para) 52 | 53 | assert.Equal(t, para.CustomIdentifier, payload.GenerateMackerelName()) 54 | assert.Equal(t, para.DisplayName, "Test") 55 | assert.Equal(t, para.Name, payload.GenerateMackerelName()) 56 | assert.Equal(t, para.RoleFullnames, []string{ 57 | "SakuraCloud:Router", 58 | "SakuraCloud:Zone-is1b", 59 | "SakuraCloud:tag1", 60 | "SakuraCloud:tag2", 61 | }) 62 | assert.Equal(t, para.Interfaces[0].Name, "eth0") 63 | assert.Equal(t, para.Interfaces[0].IPAddress, "192.168.0.1") 64 | assert.Equal(t, para.Interfaces[0].MacAddress, "") 65 | 66 | assert.Equal(t, para.Interfaces[1].Name, "eth1") 67 | assert.Equal(t, para.Interfaces[1].IPAddress, "192.168.0.2") 68 | assert.Equal(t, para.Interfaces[1].MacAddress, "") 69 | 70 | assert.Equal(t, para.Interfaces[2].Name, "eth2") 71 | assert.Equal(t, para.Interfaces[2].IPAddress, "192.168.0.3") 72 | assert.Equal(t, para.Interfaces[2].MacAddress, "") 73 | 74 | }, errFunc, errFunc) 75 | } 76 | -------------------------------------------------------------------------------- /vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "Lf3uUXTkKK5DJ37BxQvxO1Fq+K8=", 7 | "origin": "github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew", 8 | "path": "github.com/davecgh/go-spew/spew", 9 | "revision": "6d212800a42e8ab5c146b8ace3490ee17e5225f9", 10 | "revisionTime": "2016-09-07T16:21:46Z" 11 | }, 12 | { 13 | "checksumSHA1": "mBaHKsGL3Tv1jxtmQ5xxoqiZ7lE=", 14 | "path": "github.com/mackerelio/mackerel-client-go", 15 | "revision": "068671c5003e93f9aef915ea7da710be2e4b20f5", 16 | "revisionTime": "2016-07-08T05:18:08Z" 17 | }, 18 | { 19 | "checksumSHA1": "LuFv4/jlrmFNnDb/5SCSEPAM9vU=", 20 | "origin": "github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib", 21 | "path": "github.com/pmezard/go-difflib/difflib", 22 | "revision": "792786c7400a136282c1664665ae0a8db921c6c2", 23 | "revisionTime": "2016-01-10T10:55:54Z" 24 | }, 25 | { 26 | "checksumSHA1": "AIhWqbjvTTFHGnV/k4mQID2HsOo=", 27 | "path": "github.com/sacloud/libsacloud", 28 | "revision": "3c730e12dd3b0f0bc9bd5462136c8388f7e2d930", 29 | "revisionTime": "2016-10-18T07:10:39Z" 30 | }, 31 | { 32 | "checksumSHA1": "1Pl38Wc1XeSecTK5UmTIQwT2v/k=", 33 | "path": "github.com/sacloud/libsacloud/api", 34 | "revision": "3c730e12dd3b0f0bc9bd5462136c8388f7e2d930", 35 | "revisionTime": "2016-10-18T07:10:39Z" 36 | }, 37 | { 38 | "checksumSHA1": "sdGyvM7C3HJ50Ba9tiUI1QMQFyY=", 39 | "path": "github.com/sacloud/libsacloud/sacloud", 40 | "revision": "3c730e12dd3b0f0bc9bd5462136c8388f7e2d930", 41 | "revisionTime": "2016-10-18T07:10:39Z" 42 | }, 43 | { 44 | "checksumSHA1": "qTiesxgZ+Fm5yiof2bGEepcWMcc=", 45 | "path": "github.com/sacloud/libsacloud/sacloud/ostype", 46 | "revision": "3c730e12dd3b0f0bc9bd5462136c8388f7e2d930", 47 | "revisionTime": "2016-10-18T07:10:39Z" 48 | }, 49 | { 50 | "checksumSHA1": "iydUphwYqZRq3WhstEdGsbvBAKs=", 51 | "path": "github.com/stretchr/testify/assert", 52 | "revision": "d77da356e56a7428ad25149ca77381849a6a5232", 53 | "revisionTime": "2016-06-15T09:26:46Z" 54 | }, 55 | { 56 | "checksumSHA1": "J1irW4tyCsDzaVDu6olx5fG2Nrs=", 57 | "path": "gopkg.in/urfave/cli.v2", 58 | "revision": "c72728f42438425ffcd487986936357e17ebba3f", 59 | "revisionTime": "2016-08-31T17:44:05Z" 60 | } 61 | ], 62 | "rootPath": "github.com/sacloud/sackerel" 63 | } 64 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/ipv6addr.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | ) 7 | 8 | // IPv6AddrAPI IPv6アドレスAPI 9 | type IPv6AddrAPI struct { 10 | *baseAPI 11 | } 12 | 13 | // NewIPv6AddrAPI IPv6アドレスAPI新規作成 14 | func NewIPv6AddrAPI(client *Client) *IPv6AddrAPI { 15 | return &IPv6AddrAPI{ 16 | &baseAPI{ 17 | client: client, 18 | FuncGetResourceURL: func() string { 19 | return "ipv6addr" 20 | }, 21 | }, 22 | } 23 | } 24 | 25 | // Read 読み取り 26 | func (api *IPv6AddrAPI) Read(ip string) (*sacloud.IPv6Addr, error) { 27 | return api.request(func(res *sacloud.Response) error { 28 | var ( 29 | method = "GET" 30 | uri = fmt.Sprintf("%s/%s", api.getResourceURL(), ip) 31 | ) 32 | 33 | return api.baseAPI.request(method, uri, nil, res) 34 | }) 35 | 36 | } 37 | 38 | // Create 新規作成 39 | func (api *IPv6AddrAPI) Create(ip string, hostName string) (*sacloud.IPv6Addr, error) { 40 | 41 | type request struct { 42 | // IPv6Addr 43 | IPv6Addr map[string]string 44 | } 45 | 46 | var ( 47 | method = "POST" 48 | uri = api.getResourceURL() 49 | body = &request{IPv6Addr: map[string]string{}} 50 | ) 51 | body.IPv6Addr["IPv6Addr"] = ip 52 | body.IPv6Addr["HostName"] = hostName 53 | 54 | return api.request(func(res *sacloud.Response) error { 55 | return api.baseAPI.request(method, uri, body, res) 56 | }) 57 | } 58 | 59 | // Update 更新 60 | func (api *IPv6AddrAPI) Update(ip string, hostName string) (*sacloud.IPv6Addr, error) { 61 | 62 | type request struct { 63 | // IPv6Addr 64 | IPv6Addr map[string]string 65 | } 66 | 67 | var ( 68 | method = "PUT" 69 | uri = fmt.Sprintf("%s/%s", api.getResourceURL(), ip) 70 | body = &request{IPv6Addr: map[string]string{}} 71 | ) 72 | body.IPv6Addr["HostName"] = hostName 73 | 74 | return api.request(func(res *sacloud.Response) error { 75 | return api.baseAPI.request(method, uri, body, res) 76 | }) 77 | } 78 | 79 | // Delete 削除 80 | func (api *IPv6AddrAPI) Delete(ip string) (*sacloud.IPv6Addr, error) { 81 | 82 | type request struct { 83 | // IPv6Addr 84 | IPv6Addr map[string]string 85 | } 86 | 87 | var ( 88 | method = "DELETE" 89 | uri = fmt.Sprintf("%s/%s", api.getResourceURL(), ip) 90 | body = &request{IPv6Addr: map[string]string{}} 91 | ) 92 | 93 | return api.request(func(res *sacloud.Response) error { 94 | return api.baseAPI.request(method, uri, body, res) 95 | }) 96 | } 97 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_server.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "fmt" 5 | mkr "github.com/mackerelio/mackerel-client-go" 6 | "github.com/sacloud/libsacloud/sacloud" 7 | "github.com/sacloud/sackerel/job/core" 8 | "strings" 9 | ) 10 | 11 | // ServerJob サーバー変換用ジョブ 12 | func ServerJob(payload interface{}) core.JobAPI { 13 | return core.NewJob("ExchangeServer", exchangeServer, payload) 14 | } 15 | 16 | func exchangeServer(queue *core.Queue, option *core.Option, job core.JobAPI) { 17 | 18 | var payload = job.GetPayload() 19 | if payload == nil { 20 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 21 | return 22 | } 23 | 24 | if serverPayload, ok := payload.(*core.CreateHostPayload); ok { 25 | if server, ok := serverPayload.SacloudSource.(*sacloud.Server); ok { 26 | // exchange [sacloud.Server => mkr.CreateHostParam] 27 | serverPayload.MackerelHostParam = exchangeServerToMackerelHost( 28 | serverPayload.GenerateMackerelName(), 29 | serverPayload.SacloudZone, 30 | server) 31 | 32 | // trigger next route 33 | queue.PushRequest("exchanged-server", serverPayload) 34 | 35 | } else { 36 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.Server]", job.GetName())) 37 | return 38 | } 39 | 40 | } else { 41 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [*core.CreateHostPayload]", job.GetName())) 42 | return 43 | } 44 | 45 | } 46 | 47 | func exchangeServerToMackerelHost(mackerelName string, zone string, server *sacloud.Server) *mkr.CreateHostParam { 48 | 49 | p := &mkr.CreateHostParam{ 50 | Name: mackerelName, 51 | DisplayName: server.Name, 52 | CustomIdentifier: mackerelName, 53 | RoleFullnames: []string{ 54 | "SakuraCloud:Server", 55 | fmt.Sprintf("SakuraCloud:Zone-%s", zone), 56 | }, 57 | } 58 | 59 | for _, tag := range server.Tags { 60 | if tag != "" && !strings.HasPrefix(tag, "@") { 61 | p.RoleFullnames = append(p.RoleFullnames, fmt.Sprintf("SakuraCloud:%s", tag)) 62 | } 63 | } 64 | 65 | for i, nic := range server.Interfaces { 66 | 67 | ip := "" 68 | if nic.Switch != nil { 69 | ip = nic.IPAddress 70 | if nic.Switch.Scope != sacloud.ESCopeShared { 71 | ip = nic.UserIPAddress 72 | } 73 | } 74 | 75 | p.Interfaces = append(p.Interfaces, mkr.Interface{ 76 | Name: fmt.Sprintf("eth%d", i), 77 | IPAddress: ip, 78 | MacAddress: nic.MACAddress, 79 | }) 80 | } 81 | 82 | return p 83 | } 84 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/auth_status.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // AuthStatus 現在の認証状態 4 | type AuthStatus struct { 5 | // Account アカウント 6 | Account *Account 7 | // AuthClass 認証クラス 8 | AuthClass EAuthClass `json:",omitempty"` 9 | // AuthMethod 認証方法 10 | AuthMethod EAuthMethod `json:",omitempty"` 11 | // ExternalPermission 他サービスへのアクセス権 12 | ExternalPermission string `json:",omitempty"` // REMARK : +区切り文字列 13 | // IsAPIKey APIキーでのアクセスフラグ 14 | IsAPIKey bool `json:",omitempty"` 15 | // Member 会員情報 16 | Member *Member 17 | // OperationPenalty オペレーションペナルティ 18 | OperationPenalty string `json:",omitempty"` // REMARK : none以外の値が不明なためstringで受けておく 19 | // Permission 権限 20 | Permission EPermission `json:",omitempty"` 21 | // IsOk 結果 22 | IsOk bool `json:"is_ok,omitempty"` 23 | 24 | // RESTFilter [unknown type] `json:",omitempty"` 25 | // User [unknown type] `json:",omitempty"` 26 | 27 | } 28 | 29 | // -------------------------------------------------------- 30 | 31 | // EAuthClass 認証種別 32 | type EAuthClass string 33 | 34 | var ( 35 | // EAuthClassAccount アカウント認証 36 | EAuthClassAccount = EAuthClass("account") 37 | ) 38 | 39 | // -------------------------------------------------------- 40 | 41 | // EAuthMethod 認証方法 42 | type EAuthMethod string 43 | 44 | var ( 45 | // EAuthMethodAPIKey APIキー認証 46 | EAuthMethodAPIKey = EAuthMethod("apikey") 47 | ) 48 | 49 | // -------------------------------------------------------- 50 | 51 | // EExternalPermission 他サービスへのアクセス権 52 | type EExternalPermission string 53 | 54 | var ( 55 | // EExternalPermissionBill 請求情報 56 | EExternalPermissionBill = EExternalPermission("bill") 57 | // EExternalPermissionCDN ウェブアクセラレータ 58 | EExternalPermissionCDN = EExternalPermission("cdn") 59 | ) 60 | 61 | // -------------------------------------------------------- 62 | 63 | // EOperationPenalty ペナルティ 64 | type EOperationPenalty string 65 | 66 | var ( 67 | // EOperationPenaltyNone ペナルティなし 68 | EOperationPenaltyNone = EOperationPenalty("none") 69 | ) 70 | 71 | // -------------------------------------------------------- 72 | 73 | // EPermission アクセスレベル 74 | type EPermission string 75 | 76 | var ( 77 | // EPermissionCreate 作成・削除権限 78 | EPermissionCreate = EPermission("create") 79 | 80 | // EPermissionArrange 設定変更権限 81 | EPermissionArrange = EPermission("arrange") 82 | 83 | // EPermissionPower 電源操作権限 84 | EPermissionPower = EPermission("power") 85 | 86 | // EPermissionView リソース閲覧権限 87 | EPermissionView = EPermission("view") 88 | ) 89 | -------------------------------------------------------------------------------- /vendor/github.com/mackerelio/mackerel-client-go/README.md: -------------------------------------------------------------------------------- 1 | mackerel-client-go 2 | ================== 3 | 4 | [![Build Status](https://travis-ci.org/mackerelio/mackerel-client-go.svg?branch=master)][travis] 5 | [![Coverage Status](https://coveralls.io/repos/mackerelio/mackerel-client-go/badge.png?branch=master)][coveralls] 6 | [![GoDoc](https://godoc.org/github.com/mackerelio/mackerel-client-go?status.svg)][godoc] 7 | 8 | [travis]: https://travis-ci.org/mackerelio/mackerel-client-go 9 | [coveralls]: https://coveralls.io/r/mackerelio/mackerel-client-go?branch=master 10 | [godoc]: https://godoc.org/github.com/mackerelio/mackerel-client-go 11 | 12 | mackerel-client-go is a Go client library for [mackerel.io API](http://help-ja.mackerel.io/entry/spec/api/v0). 13 | 14 | # Usage 15 | 16 | ```go 17 | import mkr "github.com/mackerelio/mackerel-client-go" 18 | ``` 19 | 20 | ```go 21 | client = mkr.NewClient("") 22 | 23 | hosts, err := client.FindHosts(&mkr.FindHostsParam{ 24 | Service: "My-Service", 25 | Roles: []string{"proxy"}, 26 | Statuses: []string{"working"} 27 | }) 28 | 29 | err := client.PostServiceMetricValues("My-Service", []*mkr.MetricValue{ 30 | &mkr.MetricValue{ 31 | Name: "proxy.access_log.latency", 32 | Time: 123456789, 33 | Value: 500, 34 | }, 35 | }) 36 | ``` 37 | 38 | # CAUTION 39 | 40 | Now, mackerel-client-go is an ALPHA version. In the future release, it may change it's interface. 41 | 42 | # CONTRIBUTION 43 | 44 | 1. Fork ([https://github.com/mackerelio/mackerel-client-go/fork](https://github.com/mackerelio/mackerel-client-go/fork)) 45 | 1. Create a feature branch 46 | 1. Commit your changes 47 | 1. Rebase your local changes against the master branch 48 | 1. Run test suite with the `go test ./...` command and confirm that it passes 49 | 1. Run `gofmt -s` 50 | 1. Create new Pull Request 51 | 52 | License 53 | ---------- 54 | 55 | Copyright 2014 Hatena Co., Ltd. 56 | 57 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 58 | 59 | http://www.apache.org/licenses/LICENSE-2.0 60 | 61 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 62 | -------------------------------------------------------------------------------- /job/worker/mackerel/reconcile_by_mac_address.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | mkr "github.com/mackerelio/mackerel-client-go" 5 | "github.com/sacloud/sackerel/job/core" 6 | "strings" 7 | ) 8 | 9 | // ReconcileByMACAddressJob Mackerel上のホストから同一のMACアドレスを持つホストを検索 10 | func ReconcileByMACAddressJob(payload interface{}) core.JobAPI { 11 | return core.NewJob("MackerelReconcileHosts", reconcileByMACAddress, payload) 12 | } 13 | 14 | func reconcileByMACAddress(queue *core.Queue, option *core.Option, job core.JobAPI) { 15 | 16 | // 全ホスト取得。重いかもしれない REMARKS[要改善] 17 | client := getClient(option) 18 | findOption := &mkr.FindHostsParam{ 19 | Statuses: []string{ 20 | string(core.MackerelHostStatusWorking), 21 | string(core.MackerelHostStatusStandby), 22 | string(core.MackerelHostStatusPowerOff), 23 | string(core.MackerelHostStatusMaintenance), 24 | }, 25 | } 26 | allHosts, err := client.FindHosts(findOption) 27 | 28 | if err != nil { 29 | queue.PushError(err) 30 | return 31 | } 32 | 33 | for _, target := range allHosts { 34 | if !isNeedReconcile(target) { 35 | continue 36 | } 37 | 38 | found, fromAgentHost := findMatchMACAddressHost(allHosts, target) 39 | if found { 40 | payload := &core.ReconcileHostsPayload{ 41 | FromAgentHost: fromAgentHost, 42 | FromSackerelHost: target, 43 | } 44 | queue.PushRequest("reconcile-host", payload) 45 | } 46 | } 47 | } 48 | 49 | func isNeedReconcile(target *mkr.Host) bool { 50 | // - NICが1つ以上あり、MACアドレスが設定されていること 51 | if len(target.Interfaces) == 0 || target.Interfaces[0].MacAddress == "" { 52 | return false 53 | } 54 | 55 | // - FullRollName に "SakuraCloud:Server"が存在すること 56 | res := false 57 | roleFullNames := target.GetRoleFullnames() 58 | for _, name := range roleFullNames { 59 | if name == "SakuraCloud:Server" { 60 | res = true 61 | break 62 | } 63 | } 64 | 65 | return res 66 | } 67 | 68 | // findMatchMACAddressHost 同一のMACアドレスを持つホストを検索、ヒットした最初のホストを返す 69 | func findMatchMACAddressHost(sources []*mkr.Host, target *mkr.Host) (bool, *mkr.Host) { 70 | targetMACAddress := getMACAddress(target) 71 | for _, source := range sources { 72 | // 同一IDは除く 73 | if source.ID == target.ID { 74 | continue 75 | } 76 | sourceMACAddress := getMACAddress(source) 77 | if strings.ToLower(targetMACAddress) == strings.ToLower(sourceMACAddress) { 78 | return true, source 79 | } 80 | } 81 | 82 | return false, nil 83 | } 84 | 85 | func getMACAddress(target *mkr.Host) string { 86 | if len(target.Interfaces) == 0 { 87 | return "" 88 | } 89 | return target.Interfaces[0].MacAddress 90 | } 91 | -------------------------------------------------------------------------------- /vendor/gopkg.in/urfave/cli.v2/flag-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Bool", 4 | "type": "bool", 5 | "context_default": "false", 6 | "parser": "strconv.ParseBool(f.Value.String())" 7 | }, 8 | { 9 | "name": "Duration", 10 | "type": "time.Duration", 11 | "doctail": " (see https://golang.org/pkg/time/#ParseDuration)", 12 | "context_default": "0", 13 | "parser": "time.ParseDuration(f.Value.String())" 14 | }, 15 | { 16 | "name": "Float64", 17 | "type": "float64", 18 | "context_default": "0", 19 | "parser": "strconv.ParseFloat(f.Value.String(), 64)" 20 | }, 21 | { 22 | "name": "Generic", 23 | "type": "Generic", 24 | "dest": false, 25 | "context_default": "nil", 26 | "context_type": "interface{}" 27 | }, 28 | { 29 | "name": "Int64", 30 | "type": "int64", 31 | "context_default": "0", 32 | "parser": "strconv.ParseInt(f.Value.String(), 0, 64)" 33 | }, 34 | { 35 | "name": "Int", 36 | "type": "int", 37 | "context_default": "0", 38 | "parser": "strconv.ParseInt(f.Value.String(), 0, 64)", 39 | "parser_cast": "int(parsed)" 40 | }, 41 | { 42 | "name": "IntSlice", 43 | "type": "*IntSlice", 44 | "dest": false, 45 | "context_default": "nil", 46 | "context_type": "[]int", 47 | "parser": "(f.Value.(*IntSlice)).Value(), error(nil)" 48 | }, 49 | { 50 | "name": "Int64Slice", 51 | "type": "*Int64Slice", 52 | "dest": false, 53 | "context_default": "nil", 54 | "context_type": "[]int64", 55 | "parser": "(f.Value.(*Int64Slice)).Value(), error(nil)" 56 | }, 57 | { 58 | "name": "Float64Slice", 59 | "type": "*Float64Slice", 60 | "dest": false, 61 | "context_default": "nil", 62 | "context_type": "[]float64", 63 | "parser": "(f.Value.(*Float64Slice)).Value(), error(nil)" 64 | }, 65 | { 66 | "name": "String", 67 | "type": "string", 68 | "context_default": "\"\"", 69 | "parser": "f.Value.String(), error(nil)" 70 | }, 71 | { 72 | "name": "StringSlice", 73 | "type": "*StringSlice", 74 | "dest": false, 75 | "context_default": "nil", 76 | "context_type": "[]string", 77 | "parser": "(f.Value.(*StringSlice)).Value(), error(nil)" 78 | }, 79 | { 80 | "name": "Uint64", 81 | "type": "uint64", 82 | "context_default": "0", 83 | "parser": "strconv.ParseUint(f.Value.String(), 0, 64)" 84 | }, 85 | { 86 | "name": "Uint", 87 | "type": "uint", 88 | "context_default": "0", 89 | "parser": "strconv.ParseUint(f.Value.String(), 0, 64)", 90 | "parser_cast": "uint(parsed)" 91 | } 92 | ] 93 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/interface.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | ) 7 | 8 | // InterfaceAPI インターフェースAPI 9 | type InterfaceAPI struct { 10 | *baseAPI 11 | } 12 | 13 | // NewInterfaceAPI インターフェースAPI作成 14 | func NewInterfaceAPI(client *Client) *InterfaceAPI { 15 | return &InterfaceAPI{ 16 | &baseAPI{ 17 | client: client, 18 | FuncGetResourceURL: func() string { 19 | return "interface" 20 | }, 21 | }, 22 | } 23 | } 24 | 25 | // CreateAndConnectToServer 新規作成しサーバーへ接続する 26 | func (api *InterfaceAPI) CreateAndConnectToServer(serverID int64) (*sacloud.Interface, error) { 27 | iface := api.New() 28 | iface.Server = &sacloud.Server{ 29 | // Resource 30 | Resource: &sacloud.Resource{ID: serverID}, 31 | } 32 | return api.Create(iface) 33 | } 34 | 35 | // ConnectToSwitch スイッチへ接続する 36 | func (api *InterfaceAPI) ConnectToSwitch(interfaceID int64, switchID int64) (bool, error) { 37 | var ( 38 | method = "PUT" 39 | uri = fmt.Sprintf("%s/%d/to/switch/%d", api.getResourceURL(), interfaceID, switchID) 40 | ) 41 | return api.modify(method, uri, nil) 42 | } 43 | 44 | // ConnectToSharedSegment 共有セグメントへ接続する 45 | func (api *InterfaceAPI) ConnectToSharedSegment(interfaceID int64) (bool, error) { 46 | var ( 47 | method = "PUT" 48 | uri = fmt.Sprintf("%s/%d/to/switch/shared", api.getResourceURL(), interfaceID) 49 | ) 50 | return api.modify(method, uri, nil) 51 | } 52 | 53 | // DisconnectFromSwitch スイッチと切断する 54 | func (api *InterfaceAPI) DisconnectFromSwitch(interfaceID int64) (bool, error) { 55 | var ( 56 | method = "DELETE" 57 | uri = fmt.Sprintf("%s/%d/to/switch", api.getResourceURL(), interfaceID) 58 | ) 59 | return api.modify(method, uri, nil) 60 | } 61 | 62 | // Monitor アクティビティーモニター取得 63 | func (api *InterfaceAPI) Monitor(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) { 64 | return api.baseAPI.monitor(id, body) 65 | } 66 | 67 | // ConnectToPacketFilter パケットフィルター適用 68 | func (api *InterfaceAPI) ConnectToPacketFilter(interfaceID int64, packetFilterID int64) (bool, error) { 69 | var ( 70 | method = "PUT" 71 | uri = fmt.Sprintf("/%s/%d/to/packetfilter/%d", api.getResourceURL(), interfaceID, packetFilterID) 72 | ) 73 | return api.modify(method, uri, nil) 74 | } 75 | 76 | // DisconnectFromPacketFilter パケットフィルター切断 77 | func (api *InterfaceAPI) DisconnectFromPacketFilter(interfaceID int64) (bool, error) { 78 | var ( 79 | method = "DELETE" 80 | uri = fmt.Sprintf("/%s/%d/to/packetfilter", api.getResourceURL(), interfaceID) 81 | ) 82 | return api.modify(method, uri, nil) 83 | } 84 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_database.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "fmt" 5 | mkr "github.com/mackerelio/mackerel-client-go" 6 | "github.com/sacloud/libsacloud/sacloud" 7 | "github.com/sacloud/sackerel/job/core" 8 | "strings" 9 | ) 10 | 11 | // DatabaseJob データベース変換用ジョブ 12 | func DatabaseJob(payload interface{}) core.JobAPI { 13 | return core.NewJob("ExchangeDatabase", exchangeDatabase, payload) 14 | } 15 | 16 | func exchangeDatabase(queue *core.Queue, option *core.Option, job core.JobAPI) { 17 | 18 | var payload = job.GetPayload() 19 | if payload == nil { 20 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 21 | return 22 | } 23 | 24 | if databasePayload, ok := payload.(*core.CreateHostPayload); ok { 25 | if database, ok := databasePayload.SacloudSource.(*sacloud.Database); ok { 26 | // exchange [sacloud.Database => mkr.CreateHostParam] 27 | databasePayload.MackerelHostParam = exchangeDatabaseToMackerelHost( 28 | databasePayload.GenerateMackerelName(), 29 | databasePayload.SacloudZone, 30 | database) 31 | 32 | // trigger next route 33 | queue.PushRequest("exchanged-database", databasePayload) 34 | 35 | } else { 36 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.Database]", job.GetName())) 37 | return 38 | } 39 | 40 | } else { 41 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [*core.CreateHostPayload]", job.GetName())) 42 | return 43 | } 44 | 45 | } 46 | 47 | func exchangeDatabaseToMackerelHost(mackerelName string, zone string, database *sacloud.Database) *mkr.CreateHostParam { 48 | 49 | p := &mkr.CreateHostParam{ 50 | Name: mackerelName, 51 | DisplayName: database.Name, 52 | CustomIdentifier: mackerelName, 53 | RoleFullnames: []string{ 54 | "SakuraCloud:Database", 55 | fmt.Sprintf("SakuraCloud:Zone-%s", zone), 56 | }, 57 | } 58 | 59 | for _, tag := range database.Tags { 60 | if tag != "" && !strings.HasPrefix(tag, "@") { 61 | p.RoleFullnames = append(p.RoleFullnames, fmt.Sprintf("SakuraCloud:%s", tag)) 62 | } 63 | } 64 | 65 | if len(database.Interfaces) > 0 && database.Interfaces[0].Switch != nil { 66 | ip := database.Interfaces[0].IPAddress // 共有セグメントに接続されている場合 67 | if database.Interfaces[0].Switch.Scope != sacloud.ESCopeShared { 68 | // スイッチに接続されている場合 69 | ip = database.Remark.Servers[0].(map[string]interface{})["IPAddress"].(string) 70 | } 71 | 72 | p.Interfaces = append(p.Interfaces, mkr.Interface{ 73 | Name: fmt.Sprintf("eth%d", 0), 74 | IPAddress: ip, 75 | MacAddress: "", 76 | }) 77 | } 78 | 79 | return p 80 | } 81 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_loadbalancer.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "fmt" 5 | mkr "github.com/mackerelio/mackerel-client-go" 6 | "github.com/sacloud/libsacloud/sacloud" 7 | "github.com/sacloud/sackerel/job/core" 8 | "strings" 9 | ) 10 | 11 | // LoadBalancerJob ロードバランサー変換用ジョブ 12 | func LoadBalancerJob(payload interface{}) core.JobAPI { 13 | return core.NewJob("ExchangeLoadBalancer", exchangeLoadBalancer, payload) 14 | } 15 | 16 | func exchangeLoadBalancer(queue *core.Queue, option *core.Option, job core.JobAPI) { 17 | 18 | var payload = job.GetPayload() 19 | if payload == nil { 20 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 21 | return 22 | } 23 | 24 | if loadbalancerPayload, ok := payload.(*core.CreateHostPayload); ok { 25 | if loadbalancer, ok := loadbalancerPayload.SacloudSource.(*sacloud.LoadBalancer); ok { 26 | // exchange [sacloud.LoadBalancer => mkr.CreateHostParam] 27 | loadbalancerPayload.MackerelHostParam = exchangeLoadBalancerToMackerelHost( 28 | loadbalancerPayload.GenerateMackerelName(), 29 | loadbalancerPayload.SacloudZone, 30 | loadbalancer) 31 | 32 | // trigger next route 33 | queue.PushRequest("exchanged-loadbalancer", loadbalancerPayload) 34 | 35 | } else { 36 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.LoadBalancer]", job.GetName())) 37 | return 38 | } 39 | 40 | } else { 41 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [*core.CreateHostPayload]", job.GetName())) 42 | return 43 | } 44 | 45 | } 46 | 47 | func exchangeLoadBalancerToMackerelHost(mackerelName string, zone string, loadbalancer *sacloud.LoadBalancer) *mkr.CreateHostParam { 48 | 49 | p := &mkr.CreateHostParam{ 50 | Name: mackerelName, 51 | DisplayName: loadbalancer.Name, 52 | CustomIdentifier: mackerelName, 53 | RoleFullnames: []string{ 54 | "SakuraCloud:LoadBalancer", 55 | fmt.Sprintf("SakuraCloud:Zone-%s", zone), 56 | }, 57 | } 58 | for _, tag := range loadbalancer.Tags { 59 | if tag != "" && !strings.HasPrefix(tag, "@") { 60 | p.RoleFullnames = append(p.RoleFullnames, fmt.Sprintf("SakuraCloud:%s", tag)) 61 | } 62 | } 63 | 64 | p.Interfaces = append(p.Interfaces, mkr.Interface{ 65 | Name: fmt.Sprintf("eth%d", 0), 66 | IPAddress: loadbalancer.Remark.Servers[0].(map[string]interface{})["IPAddress"].(string), 67 | MacAddress: "", 68 | }) 69 | if len(loadbalancer.Remark.Servers) > 1 { 70 | p.Interfaces = append(p.Interfaces, mkr.Interface{ 71 | Name: fmt.Sprintf("eth%d", 1), 72 | IPAddress: loadbalancer.Remark.Servers[1].(map[string]interface{})["IPAddress"].(string), 73 | MacAddress: "", 74 | }) 75 | } 76 | 77 | return p 78 | } 79 | -------------------------------------------------------------------------------- /job/worker/sacloud/collect_router_metrics.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | "github.com/sacloud/sackerel/job/core" 7 | "time" 8 | ) 9 | 10 | // CollectRouterMetricsAllJob 過去分含めたルーターメトリクス(Interface)を取得するジョブ 11 | func CollectRouterMetricsAllJob(payload interface{}) core.JobAPI { 12 | return core.NewJob("CollectMetricsRouterAll", collectRouterMetricsAll, payload) 13 | } 14 | 15 | // CollectRouterMetricsLatestJob 直近のルーターメトリクス(Interface)を取得するジョブ 16 | func CollectRouterMetricsLatestJob(payload interface{}) core.JobAPI { 17 | return core.NewJob("CollectMetricsRouterLatest", collectRouterMetricsLatest, payload) 18 | } 19 | 20 | func collectRouterMetricsAll(queue *core.Queue, option *core.Option, job core.JobAPI) { 21 | collectRouterMetricsInner(queue, option, job, nil) 22 | } 23 | 24 | func collectRouterMetricsLatest(queue *core.Queue, option *core.Option, job core.JobAPI) { 25 | 26 | end := time.Now() 27 | start := end.Add(-option.MetricsHistoryPeriod) 28 | req := sacloud.NewResourceMonitorRequest(&start, &end) 29 | collectRouterMetricsInner(queue, option, job, req) 30 | } 31 | 32 | func collectRouterMetricsInner(queue *core.Queue, option *core.Option, job core.JobAPI, req *sacloud.ResourceMonitorRequest) { 33 | var payload = job.GetPayload() 34 | if payload == nil { 35 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 36 | return 37 | } 38 | 39 | // check payload types 40 | var sourcePayload *core.SourcePayload 41 | 42 | if s, ok := payload.(core.SourcePayloadHolder); ok { 43 | sourcePayload = s.GetSourcePayload() 44 | source := sourcePayload.SacloudSource 45 | if _, ok := source.(*sacloud.Internet); !ok { 46 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.Router]", job.GetName())) 47 | return 48 | } 49 | } else { 50 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [core.SourcePayloadHolder]", job.GetName())) 51 | return 52 | } 53 | 54 | if sourcePayload.MackerelHostStatus == core.MackerelHostStatusMaintenance { 55 | queue.PushWarn(fmt.Errorf("SakuraCloud resource['%d'] is still maintenance state. '%s' is skipped", sourcePayload.SacloudResourceID, job.GetName())) 56 | return 57 | } 58 | 59 | // Create the collect-metrics payload 60 | metricsPayload := core.NewCollectMetricsPayload(sourcePayload) 61 | client := getClient(option, sourcePayload.SacloudZone) 62 | 63 | // interfaces 64 | nicMetrics, err := client.Internet.Monitor(sourcePayload.SacloudResourceID, req) 65 | if err != nil { 66 | queue.PushError(err) 67 | return 68 | } 69 | metricsPayload.Metrics.Interface = append(metricsPayload.Metrics.Interface, nicMetrics) 70 | 71 | queue.PushRequest("collected-router-metrics", metricsPayload) 72 | } 73 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/internet.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | "time" 7 | ) 8 | 9 | // InternetAPI ルーターAPI 10 | type InternetAPI struct { 11 | *baseAPI 12 | } 13 | 14 | // NewInternetAPI ルーターAPI作成 15 | func NewInternetAPI(client *Client) *InternetAPI { 16 | return &InternetAPI{ 17 | &baseAPI{ 18 | client: client, 19 | FuncGetResourceURL: func() string { 20 | return "internet" 21 | }, 22 | }, 23 | } 24 | } 25 | 26 | // UpdateBandWidth 帯域幅更新 27 | func (api *InternetAPI) UpdateBandWidth(id int64, bandWidth int) (*sacloud.Internet, error) { 28 | var ( 29 | method = "PUT" 30 | uri = fmt.Sprintf("%s/%d/bandwidth", api.getResourceURL(), id) 31 | body = &sacloud.Request{} 32 | ) 33 | body.Internet = &sacloud.Internet{BandWidthMbps: bandWidth} 34 | 35 | return api.request(func(res *sacloud.Response) error { 36 | return api.baseAPI.request(method, uri, body, res) 37 | }) 38 | } 39 | 40 | // EnableIPv6 IPv6有効化 41 | func (api *InternetAPI) EnableIPv6(id int64) (*sacloud.IPv6Net, error) { 42 | var ( 43 | method = "POST" 44 | uri = fmt.Sprintf("%s/%d/ipv6net", api.getResourceURL(), id) 45 | ) 46 | 47 | res := &sacloud.Response{} 48 | err := api.baseAPI.request(method, uri, nil, res) 49 | if err != nil { 50 | return nil, err 51 | } 52 | return res.IPv6Net, nil 53 | } 54 | 55 | // DisableIPv6 IPv6無効化 56 | func (api *InternetAPI) DisableIPv6(id int64, ipv6NetID int64) (bool, error) { 57 | var ( 58 | method = "DELETE" 59 | uri = fmt.Sprintf("%s/%d/ipv6net/%d", api.getResourceURL(), id, ipv6NetID) 60 | ) 61 | 62 | res := &sacloud.Response{} 63 | err := api.baseAPI.request(method, uri, nil, res) 64 | if err != nil { 65 | return false, err 66 | } 67 | return true, nil 68 | } 69 | 70 | // SleepWhileCreating 作成完了まで待機 71 | func (api *InternetAPI) SleepWhileCreating(internetID int64, timeout time.Duration) error { 72 | current := 0 * time.Second 73 | interval := 5 * time.Second 74 | 75 | var item *sacloud.Internet 76 | var err error 77 | //READ 78 | for item == nil && timeout > current { 79 | item, err = api.Read(internetID) 80 | 81 | if err != nil { 82 | time.Sleep(interval) 83 | current = current + interval 84 | err = nil 85 | } 86 | } 87 | 88 | if err != nil { 89 | return err 90 | } 91 | if current > timeout { 92 | return fmt.Errorf("Timeout: Can't read /internet/%d", internetID) 93 | } 94 | 95 | return nil 96 | 97 | } 98 | 99 | // Monitor アクティビティーモニター取得 100 | func (api *InternetAPI) Monitor(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) { 101 | return api.baseAPI.monitor(id, body) 102 | } 103 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/switch.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "time" 7 | ) 8 | 9 | // Switch スイッチ 10 | type Switch struct { 11 | *Resource 12 | // Name 名称 13 | Name string `json:",omitempty"` 14 | // Description 説明 15 | Description string `json:",omitempty"` 16 | // ServerCount 接続サーバー数 17 | ServerCount int `json:",omitempty"` 18 | // ApplianceCount 接続アプライアンス数 19 | ApplianceCount int `json:",omitempty"` 20 | // Scope スコープ 21 | Scope EScope `json:",omitempty"` 22 | // Subnet サブネット 23 | Subnet *Subnet `json:",omitempty"` 24 | // UserSubnet ユーザー定義サブネット 25 | UserSubnet *Subnet `json:",omitempty"` 26 | //HybridConnection //REMARK: !!ハイブリッド接続 not support!! 27 | // ServerClass サービスクラス 28 | ServerClass string `json:",omitempty"` 29 | // CreatedAt 作成日時 30 | CreatedAt *time.Time `json:",omitempty"` 31 | // Icon アイコン 32 | Icon *Icon `json:",omitempty"` 33 | *TagsType 34 | // Subnets サブネット 35 | Subnets []SwitchSubnet `json:",omitempty"` 36 | // IPv6Nets IPv6サブネットリスト 37 | IPv6Nets []IPv6Net `json:",omitempty"` 38 | // Internet ルーター 39 | Internet *Internet `json:",omitempty"` 40 | // Bridge ブリッジ 41 | Bridge *Bridge `json:",omitempty"` 42 | } 43 | 44 | // SwitchSubnet スイッチサブネット 45 | type SwitchSubnet struct { 46 | *Subnet 47 | // IPAddresses IPアドレス範囲 48 | IPAddresses struct { 49 | // Min IPアドレス開始 50 | Min string `json:",omitempty"` 51 | // Max IPアドレス終了 52 | Max string `json:",omitempty"` 53 | } 54 | } 55 | 56 | // GetDefaultIPAddressesForVPCRouter VPCルーター接続用にサブネットからIPアドレスを3つ取得 57 | func (s *Switch) GetDefaultIPAddressesForVPCRouter() (string, string, string, error) { 58 | 59 | if s.Subnets == nil || len(s.Subnets) < 1 { 60 | return "", "", "", fmt.Errorf("switch[%d].Subnets is nil", s.ID) 61 | } 62 | 63 | baseAddress := net.ParseIP(s.Subnets[0].IPAddresses.Min).To4() 64 | address1 := net.IPv4(baseAddress[0], baseAddress[1], baseAddress[2], baseAddress[3]+1) 65 | address2 := net.IPv4(baseAddress[0], baseAddress[1], baseAddress[2], baseAddress[3]+2) 66 | 67 | return baseAddress.String(), address1.String(), address2.String(), nil 68 | } 69 | 70 | // GetIPAddressList IPアドレス範囲内の全てのIPアドレスを取得 71 | func (s *Switch) GetIPAddressList() ([]string, error) { 72 | if s.Subnets == nil || len(s.Subnets) < 1 { 73 | return nil, fmt.Errorf("switch[%d].Subnets is nil", s.ID) 74 | } 75 | 76 | //さくらのクラウドの仕様上/24までしか割り当てできないためこのロジックでOK 77 | baseIP := net.ParseIP(s.Subnets[0].IPAddresses.Min).To4() 78 | min := baseIP[3] 79 | max := net.ParseIP(s.Subnets[0].IPAddresses.Max).To4()[3] 80 | 81 | var i byte 82 | ret := []string{} 83 | for (min + i) <= max { //境界含む 84 | ip := net.IPv4(baseIP[0], baseIP[1], baseIP[2], baseIP[3]+i) 85 | ret = append(ret, ip.String()) 86 | i++ 87 | } 88 | 89 | return ret, nil 90 | } 91 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_database_test.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/sacloud" 5 | "github.com/sacloud/sackerel/job/core" 6 | "github.com/stretchr/testify/assert" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | var database = &sacloud.Database{ 12 | Appliance: &sacloud.Appliance{ 13 | Resource: &sacloud.Resource{ID: 123456789012}, 14 | Name: "Test", 15 | TagsType: &sacloud.TagsType{ 16 | Tags: []string{"tag1", "tag2"}, 17 | }, 18 | Interfaces: []sacloud.Interface{ 19 | { 20 | IPAddress: "8.8.8.8", 21 | Switch: &sacloud.Switch{ 22 | Scope: sacloud.ESCopeShared, 23 | }, 24 | }, 25 | }, 26 | }, 27 | Remark: &sacloud.DatabaseRemark{ 28 | ApplianceRemarkBase: &sacloud.ApplianceRemarkBase{ 29 | Servers: []interface{}{ 30 | map[string]interface{}{ 31 | "IPAddress": "192.168.0.1", 32 | }, 33 | }, 34 | }, 35 | }, 36 | } 37 | 38 | func TestDatabaseJob(t *testing.T) { 39 | if !baseExchangeJobTest(t) { 40 | return 41 | } 42 | 43 | databasePayload := core.NewCreateHostPayload(database, "is1b", 123456789012, reflect.TypeOf(database)) 44 | job := DatabaseJob(databasePayload) 45 | errFunc := func(err error) { 46 | assert.Fail(t, "Warn or Error log printed") 47 | } 48 | go job.Start(queue, option) 49 | jobCheckFunc(t, queue, func(v core.JobRequestAPI) { 50 | payload := v.GetPayload().(*core.CreateHostPayload) 51 | assert.NotNil(t, payload) 52 | 53 | para := payload.MackerelHostParam 54 | assert.NotNil(t, para) 55 | 56 | assert.Equal(t, para.CustomIdentifier, payload.GenerateMackerelName()) 57 | assert.Equal(t, para.DisplayName, "Test") 58 | assert.Equal(t, para.Name, payload.GenerateMackerelName()) 59 | assert.Equal(t, para.RoleFullnames, []string{ 60 | "SakuraCloud:Database", 61 | "SakuraCloud:Zone-is1b", 62 | "SakuraCloud:tag1", 63 | "SakuraCloud:tag2", 64 | }) 65 | assert.Equal(t, para.Interfaces[0].Name, "eth0") 66 | assert.Equal(t, para.Interfaces[0].IPAddress, "8.8.8.8") 67 | assert.Equal(t, para.Interfaces[0].MacAddress, "") 68 | 69 | }, errFunc, errFunc) 70 | 71 | database.Interfaces[0].Switch.Scope = sacloud.ESCopeUser 72 | 73 | databasePayload = core.NewCreateHostPayload(database, "is1b", 123456789012, reflect.TypeOf(database)) 74 | job = DatabaseJob(databasePayload) 75 | go job.Start(queue, option) 76 | jobCheckFunc(t, queue, func(v core.JobRequestAPI) { 77 | payload := v.GetPayload().(*core.CreateHostPayload) 78 | assert.NotNil(t, payload) 79 | 80 | para := payload.MackerelHostParam 81 | assert.NotNil(t, para) 82 | 83 | assert.Equal(t, para.Interfaces[0].Name, "eth0") 84 | assert.Equal(t, para.Interfaces[0].IPAddress, "192.168.0.1") 85 | assert.Equal(t, para.Interfaces[0].MacAddress, "") 86 | 87 | }, errFunc, errFunc) 88 | 89 | } 90 | -------------------------------------------------------------------------------- /job/core/payload_types.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | mkr "github.com/mackerelio/mackerel-client-go" 6 | "reflect" 7 | ) 8 | 9 | //----------------------------------------------------------------------------- 10 | // Payload common data types 11 | //----------------------------------------------------------------------------- 12 | 13 | // MackerelHostStatus Mackerel上でのホストステータスを表す 14 | type MackerelHostStatus string 15 | 16 | var ( 17 | // MackerelHostStatusStandby "standby"ホストステータス 18 | MackerelHostStatusStandby = MackerelHostStatus("standby") 19 | 20 | // MackerelHostStatusWorking "working"ホストステータス 21 | MackerelHostStatusWorking = MackerelHostStatus("working") 22 | 23 | // MackerelHostStatusMaintenance "maintenance"ホストステータス 24 | MackerelHostStatusMaintenance = MackerelHostStatus("maintenance") 25 | 26 | // MackerelHostStatusPowerOff "poweroff"ホストステータス 27 | MackerelHostStatusPowerOff = MackerelHostStatus("poweroff") 28 | ) 29 | 30 | //----------------------------------------------------------------------------- 31 | // Payload interfaces 32 | //----------------------------------------------------------------------------- 33 | 34 | // MackerelFindParamHolder Mackerelからのホスト検索用パラメータを保持していることを表すインターフェース 35 | type MackerelFindParamHolder interface { 36 | GetFindParam() *mkr.FindHostsParam 37 | } 38 | 39 | // SourcePayloadHolder SourcePayloadを保持していることを表すインターフェース 40 | type SourcePayloadHolder interface { 41 | GetSourcePayload() *SourcePayload 42 | } 43 | 44 | //----------------------------------------------------------------------------- 45 | // SourceMetaPayload 46 | //----------------------------------------------------------------------------- 47 | 48 | // SourcePayload 連携元データを内包するペイロード 49 | type SourcePayload struct { 50 | SacloudSource interface{} 51 | SacloudZone string 52 | SacloudResourceID int64 53 | SourceType reflect.Type 54 | MackerelID string 55 | MackerelHost *mkr.Host 56 | MackerelHostStatus MackerelHostStatus 57 | } 58 | 59 | // GetSourcePayload ペイロードの取得 60 | func (p *SourcePayload) GetSourcePayload() *SourcePayload { 61 | return p 62 | } 63 | 64 | // GenerateMackerelName さくらのクラウド上のリソース定義を元にMackerel上でのホスト名を生成する 65 | func (p *SourcePayload) GenerateMackerelName() string { 66 | resourceID := p.SacloudResourceID 67 | if resourceID <= 0 { 68 | return "" 69 | } 70 | return fmt.Sprintf("sakuracloud-%s-%d", p.SacloudZone, resourceID) 71 | } 72 | 73 | // NewSourcePayload SourcePayloadの新規作成 74 | func NewSourcePayload(source interface{}, zone string, resourceID int64, sourceType reflect.Type) *SourcePayload { 75 | return &SourcePayload{ 76 | SacloudSource: source, 77 | SacloudZone: zone, 78 | SacloudResourceID: resourceID, 79 | SourceType: sourceType, 80 | MackerelHostStatus: MackerelHostStatusWorking, 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /job/worker/sacloud/collect_loadbalancer_metrics.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | "github.com/sacloud/sackerel/job/core" 7 | "time" 8 | ) 9 | 10 | // CollectLoadBalancerMetricsAllJob 過去分含めたロードバランサーメトリクス(Interface)を取得するジョブ 11 | func CollectLoadBalancerMetricsAllJob(payload interface{}) core.JobAPI { 12 | return core.NewJob("CollectMetricsLoadBalancerAll", collectLoadBalancerMetricsAll, payload) 13 | } 14 | 15 | // CollectLoadBalancerMetricsLatestJob 直近のロードバランサーメトリクス(Interface)を取得するジョブ 16 | func CollectLoadBalancerMetricsLatestJob(payload interface{}) core.JobAPI { 17 | return core.NewJob("CollectMetricsLoadBalancerLatest", collectLoadBalancerMetricsLatest, payload) 18 | } 19 | 20 | func collectLoadBalancerMetricsAll(queue *core.Queue, option *core.Option, job core.JobAPI) { 21 | collectLoadBalancerMetricsInner(queue, option, job, nil) 22 | } 23 | 24 | func collectLoadBalancerMetricsLatest(queue *core.Queue, option *core.Option, job core.JobAPI) { 25 | 26 | end := time.Now() 27 | start := end.Add(-option.MetricsHistoryPeriod) 28 | req := sacloud.NewResourceMonitorRequest(&start, &end) 29 | collectLoadBalancerMetricsInner(queue, option, job, req) 30 | } 31 | 32 | func collectLoadBalancerMetricsInner(queue *core.Queue, option *core.Option, job core.JobAPI, req *sacloud.ResourceMonitorRequest) { 33 | var payload = job.GetPayload() 34 | if payload == nil { 35 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 36 | return 37 | } 38 | 39 | // check payload types 40 | var sourcePayload *core.SourcePayload 41 | 42 | if s, ok := payload.(core.SourcePayloadHolder); ok { 43 | sourcePayload = s.GetSourcePayload() 44 | source := sourcePayload.SacloudSource 45 | if _, ok := source.(*sacloud.LoadBalancer); !ok { 46 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.LoadBalancer]", job.GetName())) 47 | return 48 | } 49 | } else { 50 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [core.SourcePayloadHolder]", job.GetName())) 51 | return 52 | } 53 | 54 | if sourcePayload.MackerelHostStatus == core.MackerelHostStatusMaintenance { 55 | queue.PushWarn(fmt.Errorf("SakuraCloud resource['%d'] is still maintenance state. '%s' is skipped", sourcePayload.SacloudResourceID, job.GetName())) 56 | return 57 | } 58 | 59 | // Create the collect-metrics payload 60 | metricsPayload := core.NewCollectMetricsPayload(sourcePayload) 61 | client := getClient(option, sourcePayload.SacloudZone) 62 | 63 | // interfaces 64 | nicMetrics, err := client.LoadBalancer.Monitor(sourcePayload.SacloudResourceID, req) 65 | if err != nil { 66 | queue.PushError(err) 67 | return 68 | } 69 | metricsPayload.Metrics.Interface = append(metricsPayload.Metrics.Interface, nicMetrics) 70 | 71 | queue.PushRequest("collected-loadbalancer-metrics", metricsPayload) 72 | } 73 | -------------------------------------------------------------------------------- /vendor/gopkg.in/urfave/cli.v2/errors.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | // OsExiter is the function used when the app exits. If not set defaults to os.Exit. 11 | var OsExiter = os.Exit 12 | 13 | // ErrWriter is used to write errors to the user. This can be anything 14 | // implementing the io.Writer interface and defaults to os.Stderr. 15 | var ErrWriter io.Writer = os.Stderr 16 | 17 | // MultiError is an error that wraps multiple errors. 18 | type MultiError interface { 19 | error 20 | // Errors returns a copy of the errors slice 21 | Errors() []error 22 | } 23 | 24 | // NewMultiError creates a new MultiError. Pass in one or more errors. 25 | func newMultiError(err ...error) MultiError { 26 | ret := multiError(err) 27 | return &ret 28 | } 29 | 30 | type multiError []error 31 | 32 | // Error implements the error interface. 33 | func (m *multiError) Error() string { 34 | errs := make([]string, len(*m)) 35 | for i, err := range *m { 36 | errs[i] = err.Error() 37 | } 38 | 39 | return strings.Join(errs, "\n") 40 | } 41 | 42 | // Errors returns a copy of the errors slice 43 | func (m *multiError) Errors() []error { 44 | errs := make([]error, len(*m)) 45 | for _, err := range *m { 46 | errs = append(errs, err) 47 | } 48 | return errs 49 | } 50 | 51 | // ExitCoder is the interface checked by `App` and `Command` for a custom exit 52 | // code 53 | type ExitCoder interface { 54 | error 55 | ExitCode() int 56 | } 57 | 58 | type exitError struct { 59 | exitCode int 60 | message string 61 | } 62 | 63 | // Exit wraps a message and exit code into an ExitCoder suitable for handling by 64 | // HandleExitCoder 65 | func Exit(message string, exitCode int) ExitCoder { 66 | return &exitError{ 67 | exitCode: exitCode, 68 | message: message, 69 | } 70 | } 71 | 72 | func (ee *exitError) Error() string { 73 | return ee.message 74 | } 75 | 76 | func (ee *exitError) ExitCode() int { 77 | return ee.exitCode 78 | } 79 | 80 | // HandleExitCoder checks if the error fulfills the ExitCoder interface, and if 81 | // so prints the error to stderr (if it is non-empty) and calls OsExiter with the 82 | // given exit code. If the given error is a MultiError, then this func is 83 | // called on all members of the Errors slice. 84 | func HandleExitCoder(err error) { 85 | if err == nil { 86 | return 87 | } 88 | 89 | if exitErr, ok := err.(ExitCoder); ok { 90 | if err.Error() != "" { 91 | fmt.Fprintln(ErrWriter, err) 92 | } 93 | OsExiter(exitErr.ExitCode()) 94 | return 95 | } 96 | 97 | if multiErr, ok := err.(MultiError); ok { 98 | for _, merr := range multiErr.Errors() { 99 | HandleExitCoder(merr) 100 | } 101 | return 102 | } 103 | 104 | if err.Error() != "" { 105 | fmt.Fprintln(ErrWriter, err) 106 | } 107 | OsExiter(1) 108 | } 109 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_vpcrouter.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "fmt" 5 | mkr "github.com/mackerelio/mackerel-client-go" 6 | "github.com/sacloud/libsacloud/sacloud" 7 | "github.com/sacloud/sackerel/job/core" 8 | "strings" 9 | ) 10 | 11 | // VPCRouterJob VPCルーター変換用ジョブ 12 | func VPCRouterJob(payload interface{}) core.JobAPI { 13 | return core.NewJob("ExchangeVPCRouter", exchangeVPCRouter, payload) 14 | } 15 | 16 | func exchangeVPCRouter(queue *core.Queue, option *core.Option, job core.JobAPI) { 17 | 18 | var payload = job.GetPayload() 19 | if payload == nil { 20 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 21 | return 22 | } 23 | 24 | if vpcrouterPayload, ok := payload.(*core.CreateHostPayload); ok { 25 | if vpcrouter, ok := vpcrouterPayload.SacloudSource.(*sacloud.VPCRouter); ok { 26 | // exchange [sacloud.VPCRouter => mkr.CreateHostParam] 27 | vpcrouterPayload.MackerelHostParam = exchangeVPCRouterToMackerelHost( 28 | vpcrouterPayload.GenerateMackerelName(), 29 | vpcrouterPayload.SacloudZone, 30 | vpcrouter) 31 | 32 | // trigger next route 33 | queue.PushRequest("exchanged-vpcrouter", vpcrouterPayload) 34 | 35 | } else { 36 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.VPCRouter]", job.GetName())) 37 | return 38 | } 39 | 40 | } else { 41 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [*core.CreateHostPayload]", job.GetName())) 42 | return 43 | } 44 | 45 | } 46 | 47 | func exchangeVPCRouterToMackerelHost(mackerelName string, zone string, vpcrouter *sacloud.VPCRouter) *mkr.CreateHostParam { 48 | 49 | p := &mkr.CreateHostParam{ 50 | Name: mackerelName, 51 | DisplayName: vpcrouter.Name, 52 | CustomIdentifier: mackerelName, 53 | RoleFullnames: []string{ 54 | "SakuraCloud:VPCRouter", 55 | fmt.Sprintf("SakuraCloud:Zone-%s", zone), 56 | }, 57 | } 58 | 59 | for _, tag := range vpcrouter.Tags { 60 | if tag != "" && !strings.HasPrefix(tag, "@") { 61 | p.RoleFullnames = append(p.RoleFullnames, fmt.Sprintf("SakuraCloud:%s", tag)) 62 | } 63 | } 64 | 65 | // Global IP 66 | ip := vpcrouter.Interfaces[0].IPAddress 67 | nic := vpcrouter.Settings.Router.Interfaces[0] 68 | if nic != nil && nic.VirtualIPAddress != "" { 69 | ip = nic.VirtualIPAddress 70 | } 71 | 72 | if ip != "" { 73 | p.Interfaces = append(p.Interfaces, mkr.Interface{ 74 | Name: fmt.Sprintf("eth%d", 0), 75 | IPAddress: ip, 76 | MacAddress: "", 77 | }) 78 | } 79 | 80 | // private ip 81 | for i, nic := range vpcrouter.Settings.Router.Interfaces { 82 | if i == 0 { 83 | continue 84 | } 85 | ip := nic.IPAddress[0] // 必ず存在するはず。 86 | if nic.VirtualIPAddress != "" { 87 | ip = nic.VirtualIPAddress 88 | } 89 | p.Interfaces = append(p.Interfaces, mkr.Interface{ 90 | Name: fmt.Sprintf("eth%d", i), 91 | IPAddress: ip, 92 | MacAddress: "", 93 | }) 94 | } 95 | 96 | return p 97 | } 98 | -------------------------------------------------------------------------------- /job/worker/sacloud/collect_vpcrouter_metrics.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | "github.com/sacloud/sackerel/job/core" 7 | "time" 8 | ) 9 | 10 | // CollectVPCRouterMetricsAllJob 過去分含めたVPCルーターメトリクス(Interface)を取得するジョブ 11 | func CollectVPCRouterMetricsAllJob(payload interface{}) core.JobAPI { 12 | return core.NewJob("CollectMetricsVPCRouterAll", collectVPCRouterMetricsAll, payload) 13 | } 14 | 15 | // CollectVPCRouterMetricsLatestJob 直近のVPCルーターメトリクス(Interface)を取得するジョブ 16 | func CollectVPCRouterMetricsLatestJob(payload interface{}) core.JobAPI { 17 | return core.NewJob("CollectMetricsVPCRouterLatest", collectVPCRouterMetricsLatest, payload) 18 | } 19 | 20 | func collectVPCRouterMetricsAll(queue *core.Queue, option *core.Option, job core.JobAPI) { 21 | collectVPCRouterMetricsInner(queue, option, job, nil) 22 | } 23 | 24 | func collectVPCRouterMetricsLatest(queue *core.Queue, option *core.Option, job core.JobAPI) { 25 | 26 | end := time.Now() 27 | start := end.Add(-option.MetricsHistoryPeriod) 28 | req := sacloud.NewResourceMonitorRequest(&start, &end) 29 | collectVPCRouterMetricsInner(queue, option, job, req) 30 | } 31 | 32 | func collectVPCRouterMetricsInner(queue *core.Queue, option *core.Option, job core.JobAPI, req *sacloud.ResourceMonitorRequest) { 33 | var payload = job.GetPayload() 34 | if payload == nil { 35 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 36 | return 37 | } 38 | 39 | // check payload types 40 | var vpcrouter *sacloud.VPCRouter 41 | var sourcePayload *core.SourcePayload 42 | 43 | if s, ok := payload.(core.SourcePayloadHolder); ok { 44 | sourcePayload = s.GetSourcePayload() 45 | source := sourcePayload.SacloudSource 46 | if vpcrouter, ok = source.(*sacloud.VPCRouter); !ok { 47 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.VPCRouter]", job.GetName())) 48 | return 49 | } 50 | } else { 51 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [core.SourcePayloadHolder]", job.GetName())) 52 | return 53 | } 54 | 55 | if sourcePayload.MackerelHostStatus == core.MackerelHostStatusMaintenance { 56 | queue.PushWarn(fmt.Errorf("SakuraCloud resource['%d'] is still maintenance state. '%s' is skipped", sourcePayload.SacloudResourceID, job.GetName())) 57 | return 58 | } 59 | 60 | // Create the collect-metrics payload 61 | metricsPayload := core.NewCollectMetricsPayload(sourcePayload) 62 | client := getClient(option, sourcePayload.SacloudZone) 63 | 64 | // interfaces 65 | for i, nic := range vpcrouter.Settings.Router.Interfaces { 66 | 67 | if i == 0 || nic != nil { // i == 0 はグローバルNIC用、以降はスイッチと接続があれば値がある 68 | nicMetrics, err := client.VPCRouter.MonitorBy(sourcePayload.SacloudResourceID, i, req) 69 | if err != nil { 70 | queue.PushError(err) 71 | return 72 | } 73 | metricsPayload.Metrics.Interface = append(metricsPayload.Metrics.Interface, nicMetrics) 74 | } else { 75 | // 値がないとNICインデックスがずれるためnilを入れておく 76 | metricsPayload.Metrics.Interface = append(metricsPayload.Metrics.Interface, nil) 77 | } 78 | } 79 | 80 | queue.PushRequest("collected-vpcrouter-metrics", metricsPayload) 81 | } 82 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_vpcrouter_test.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "github.com/sacloud/libsacloud/sacloud" 5 | "github.com/sacloud/sackerel/job/core" 6 | "github.com/stretchr/testify/assert" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | var vpcrouterStandard = &sacloud.VPCRouter{ 12 | Appliance: &sacloud.Appliance{ 13 | Resource: &sacloud.Resource{ID: 123456789012}, 14 | Name: "Test", 15 | TagsType: &sacloud.TagsType{ 16 | Tags: []string{"tag1", "tag2"}, 17 | }, 18 | Interfaces: []sacloud.Interface{ 19 | { 20 | IPAddress: "192.168.0.1", 21 | }, 22 | }, 23 | }, 24 | Settings: &sacloud.VPCRouterSettings{ 25 | Router: &sacloud.VPCRouterSetting{ 26 | Interfaces: []*sacloud.VPCRouterInterface{ 27 | nil, 28 | { 29 | IPAddress: []string{ 30 | "192.168.0.2", 31 | }, 32 | }, 33 | }, 34 | }, 35 | }, 36 | } 37 | 38 | var vpcrouterPremium = &sacloud.VPCRouter{ 39 | Appliance: &sacloud.Appliance{ 40 | Resource: &sacloud.Resource{ID: 123456789012}, 41 | Name: "Test", 42 | TagsType: &sacloud.TagsType{ 43 | Tags: []string{"tag1", "tag2"}, 44 | }, 45 | Interfaces: []sacloud.Interface{ 46 | {}, 47 | }, 48 | }, 49 | Settings: &sacloud.VPCRouterSettings{ 50 | Router: &sacloud.VPCRouterSetting{ 51 | Interfaces: []*sacloud.VPCRouterInterface{ 52 | { 53 | IPAddress: []string{ 54 | "8.8.8.8", 55 | "8.8.4.4", 56 | }, 57 | VirtualIPAddress: "192.168.0.1", 58 | }, 59 | { 60 | IPAddress: []string{ 61 | "8.8.8.8", 62 | "8.8.4.4", 63 | }, 64 | VirtualIPAddress: "192.168.0.2", 65 | }, 66 | }, 67 | }, 68 | }, 69 | } 70 | 71 | func TestVPCRouterJob(t *testing.T) { 72 | if !baseExchangeJobTest(t) { 73 | return 74 | } 75 | 76 | targets := []*sacloud.VPCRouter{vpcrouterStandard, vpcrouterPremium} 77 | 78 | for _, vpcrouter := range targets { 79 | vpcrouterPayload := core.NewCreateHostPayload(vpcrouter, "is1b", 123456789012, reflect.TypeOf(vpcrouter)) 80 | job := VPCRouterJob(vpcrouterPayload) 81 | errFunc := func(err error) { 82 | assert.Fail(t, "Warn or Error log printed") 83 | } 84 | go job.Start(queue, option) 85 | jobCheckFunc(t, queue, func(v core.JobRequestAPI) { 86 | payload := v.GetPayload().(*core.CreateHostPayload) 87 | assert.NotNil(t, payload) 88 | 89 | para := payload.MackerelHostParam 90 | assert.NotNil(t, para) 91 | 92 | assert.Equal(t, para.CustomIdentifier, payload.GenerateMackerelName()) 93 | assert.Equal(t, para.DisplayName, "Test") 94 | assert.Equal(t, para.Name, payload.GenerateMackerelName()) 95 | assert.Equal(t, para.RoleFullnames, []string{ 96 | "SakuraCloud:VPCRouter", 97 | "SakuraCloud:Zone-is1b", 98 | "SakuraCloud:tag1", 99 | "SakuraCloud:tag2", 100 | }) 101 | assert.Equal(t, para.Interfaces[0].Name, "eth0") 102 | assert.Equal(t, para.Interfaces[0].IPAddress, "192.168.0.1") 103 | assert.Equal(t, para.Interfaces[0].MacAddress, "") 104 | 105 | assert.Equal(t, para.Interfaces[1].Name, "eth1") 106 | assert.Equal(t, para.Interfaces[1].IPAddress, "192.168.0.2") 107 | assert.Equal(t, para.Interfaces[1].MacAddress, "") 108 | 109 | }, errFunc, errFunc) 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /job/worker/exchange/exchange_router.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "fmt" 5 | mkr "github.com/mackerelio/mackerel-client-go" 6 | "github.com/sacloud/libsacloud/sacloud" 7 | "github.com/sacloud/sackerel/job/core" 8 | "net" 9 | "strings" 10 | ) 11 | 12 | // RouterJob ルーター変換用ジョブ 13 | func RouterJob(payload interface{}) core.JobAPI { 14 | return core.NewJob("ExchangeRouter", exchangeRouter, payload) 15 | } 16 | 17 | func exchangeRouter(queue *core.Queue, option *core.Option, job core.JobAPI) { 18 | 19 | var payload = job.GetPayload() 20 | if payload == nil { 21 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 22 | return 23 | } 24 | 25 | if serverPayload, ok := payload.(*core.CreateHostPayload); ok { 26 | if router, ok := serverPayload.SacloudSource.(*sacloud.Internet); ok { 27 | // exchange [sacloud.Server => mkr.CreateHostParam] 28 | hostParam, err := exchangeRouterToMackerelHost( 29 | serverPayload.GenerateMackerelName(), 30 | serverPayload.SacloudZone, 31 | router) 32 | 33 | if err != nil { 34 | queue.PushError(err) 35 | return 36 | } 37 | 38 | serverPayload.MackerelHostParam = hostParam 39 | // trigger next route 40 | queue.PushRequest("exchanged-router", serverPayload) 41 | 42 | } else { 43 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.Server]", job.GetName())) 44 | return 45 | } 46 | 47 | } else { 48 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [*core.CreateHostPayload]", job.GetName())) 49 | return 50 | } 51 | 52 | } 53 | 54 | func exchangeRouterToMackerelHost(mackerelName string, zone string, router *sacloud.Internet) (*mkr.CreateHostParam, error) { 55 | 56 | p := &mkr.CreateHostParam{ 57 | Name: mackerelName, 58 | DisplayName: router.Name, 59 | CustomIdentifier: mackerelName, 60 | RoleFullnames: []string{ 61 | "SakuraCloud:Router", 62 | fmt.Sprintf("SakuraCloud:Zone-%s", zone), 63 | }, 64 | } 65 | 66 | // !!HACK!! 67 | for _, tag := range router.Switch.Tags { 68 | if tag != "" && !strings.HasPrefix(tag, "@") { 69 | p.RoleFullnames = append(p.RoleFullnames, fmt.Sprintf("SakuraCloud:%s", tag)) 70 | } 71 | } 72 | 73 | ipaddresses, err := getIPAddressListFromSwitchSubnet(router.Switch) 74 | if ipaddresses == nil || err != nil { 75 | return nil, err 76 | } 77 | for i, ip := range ipaddresses { 78 | p.Interfaces = append(p.Interfaces, mkr.Interface{ 79 | Name: fmt.Sprintf("eth%d", i), 80 | IPAddress: ip, 81 | MacAddress: "", 82 | }) 83 | } 84 | 85 | return p, nil 86 | } 87 | 88 | func getIPAddressListFromSwitchSubnet(s *sacloud.Switch) ([]string, error) { 89 | if s.Subnets == nil || len(s.Subnets) < 1 { 90 | return nil, fmt.Errorf("switch[%s].Subnets is nil", s.ID) 91 | } 92 | 93 | //さくらのクラウドの仕様上/24までしか割り当てできないためこのロジックでOK 94 | baseIP := net.ParseIP(s.Subnets[0].IPAddresses.Min).To4() 95 | min := baseIP[3] 96 | max := net.ParseIP(s.Subnets[0].IPAddresses.Max).To4()[3] 97 | 98 | var i byte 99 | ret := []string{} 100 | for (min + i) <= max { //境界含む 101 | ip := net.IPv4(baseIP[0], baseIP[1], baseIP[2], baseIP[3]+i) 102 | ret = append(ret, ip.String()) 103 | i++ 104 | } 105 | 106 | return ret, nil 107 | } 108 | -------------------------------------------------------------------------------- /job/worker/sacloud/collect_server_metrics.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | "github.com/sacloud/sackerel/job/core" 7 | "time" 8 | ) 9 | 10 | // CollectServerMetricsAllJob 過去分含めたサーバーメトリクス(CPU/Disk/Interface)を取得するジョブ 11 | func CollectServerMetricsAllJob(payload interface{}) core.JobAPI { 12 | return core.NewJob("CollectMetricsServerAll", collectServerMetricsAll, payload) 13 | } 14 | 15 | // CollectServerMetricsLatestJob 直近のサーバーメトリクス(CPU/Disk/Interface)を取得するジョブ 16 | func CollectServerMetricsLatestJob(payload interface{}) core.JobAPI { 17 | return core.NewJob("CollectMetricsServerLatest", collectServerMetricsLatest, payload) 18 | } 19 | 20 | func collectServerMetricsAll(queue *core.Queue, option *core.Option, job core.JobAPI) { 21 | collectServerMetricsInner(queue, option, job, nil) 22 | } 23 | 24 | func collectServerMetricsLatest(queue *core.Queue, option *core.Option, job core.JobAPI) { 25 | 26 | end := time.Now() 27 | start := end.Add(-option.MetricsHistoryPeriod) 28 | req := sacloud.NewResourceMonitorRequest(&start, &end) 29 | collectServerMetricsInner(queue, option, job, req) 30 | } 31 | 32 | func collectServerMetricsInner(queue *core.Queue, option *core.Option, job core.JobAPI, req *sacloud.ResourceMonitorRequest) { 33 | var payload = job.GetPayload() 34 | if payload == nil { 35 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 36 | return 37 | } 38 | 39 | // check payload types 40 | var server *sacloud.Server 41 | var sourcePayload *core.SourcePayload 42 | 43 | if s, ok := payload.(core.SourcePayloadHolder); ok { 44 | sourcePayload = s.GetSourcePayload() 45 | source := sourcePayload.SacloudSource 46 | if server, ok = source.(*sacloud.Server); !ok { 47 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.Server]", job.GetName())) 48 | return 49 | } 50 | } else { 51 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [core.SourcePayloadHolder]", job.GetName())) 52 | return 53 | } 54 | 55 | if sourcePayload.MackerelHostStatus == core.MackerelHostStatusMaintenance { 56 | queue.PushWarn(fmt.Errorf("SakuraCloud resource['%d'] is still maintenance state. '%s' is skipped", sourcePayload.SacloudResourceID, job.GetName())) 57 | return 58 | } 59 | 60 | // Create the collect-metrics payload 61 | metricsPayload := core.NewCollectMetricsPayload(sourcePayload) 62 | client := getClient(option, sourcePayload.SacloudZone) 63 | 64 | // cpu 65 | cpuMetrics, err := client.Server.Monitor(server.ID, req) 66 | if err != nil { 67 | queue.PushError(err) 68 | return 69 | } 70 | metricsPayload.Metrics.CPU = append(metricsPayload.Metrics.CPU, cpuMetrics) 71 | 72 | // disks 73 | for _, disk := range server.Disks { 74 | diskMetrics, err := client.Disk.Monitor(disk.ID, req) 75 | if err != nil { 76 | queue.PushError(err) 77 | return 78 | } 79 | metricsPayload.Metrics.Disk = append(metricsPayload.Metrics.Disk, diskMetrics) 80 | } 81 | 82 | // interfaces 83 | for _, nic := range server.Interfaces { 84 | nicMetrics, err := client.Interface.Monitor(nic.ID, req) 85 | if err != nil { 86 | queue.PushError(err) 87 | return 88 | } 89 | metricsPayload.Metrics.Interface = append(metricsPayload.Metrics.Interface, nicMetrics) 90 | } 91 | 92 | queue.PushRequest("collected-server-metrics", metricsPayload) 93 | } 94 | -------------------------------------------------------------------------------- /job/core/queue.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | // Queue ジョブキュー 4 | type Queue struct { 5 | Request chan JobRequestAPI 6 | Internal chan JobAPI 7 | SakuraRequest chan JobAPI 8 | MackerelRequest chan JobAPI 9 | ThrottledRequest chan JobAPI 10 | Logs *LogQueue 11 | Quit chan error 12 | } 13 | 14 | // LogQueue ログ出力用キュー 15 | type LogQueue struct { 16 | Info chan string 17 | Trace chan string 18 | Warn chan error 19 | Error chan error 20 | } 21 | 22 | var defaultLogBufferSize = 10 23 | 24 | // NewQueue ジョブキューの新規作成 25 | func NewQueue(workBufSize int, throttledReqBufSize int, sakuraReqBufSize int, mkrReqBufSize int) *Queue { 26 | return &Queue{ 27 | Request: make(chan JobRequestAPI, workBufSize), 28 | Internal: make(chan JobAPI, workBufSize), 29 | ThrottledRequest: make(chan JobAPI, throttledReqBufSize), 30 | SakuraRequest: make(chan JobAPI, sakuraReqBufSize), 31 | MackerelRequest: make(chan JobAPI, mkrReqBufSize), 32 | Logs: &LogQueue{ 33 | Info: make(chan string, defaultLogBufferSize), 34 | Trace: make(chan string, defaultLogBufferSize), 35 | Warn: make(chan error, defaultLogBufferSize), 36 | Error: make(chan error, defaultLogBufferSize), 37 | }, 38 | Quit: make(chan error), 39 | } 40 | } 41 | 42 | // PushRequest push new request to job-routing queue 43 | func (q *Queue) PushRequest(requestName string, payload interface{}) { 44 | q.Request <- &jobRequest{ 45 | name: requestName, 46 | payload: payload, 47 | } 48 | } 49 | 50 | //--------------------------------------------------------- 51 | // Push jobs 52 | //--------------------------------------------------------- 53 | 54 | // PushInternalWork push job to internal-job queue 55 | func (q *Queue) PushInternalWork(work JobAPI) { 56 | q.Internal <- work 57 | } 58 | 59 | // PushSakuraAPIWork push job to sakuraAPI-job queue 60 | func (q *Queue) PushSakuraAPIWork(work JobAPI) { 61 | q.SakuraRequest <- work 62 | } 63 | 64 | // PushMackerelAPIWork push job to mackerelAPI-job queue 65 | func (q *Queue) PushMackerelAPIWork(work JobAPI) { 66 | q.MackerelRequest <- work 67 | } 68 | 69 | // PushThrottledAPIWork push job to throttledAPI-job queue 70 | func (q *Queue) PushThrottledAPIWork(work JobAPI) { 71 | q.ThrottledRequest <- work 72 | } 73 | 74 | //--------------------------------------------------------- 75 | // Stop 76 | //--------------------------------------------------------- 77 | 78 | // Stop push stop request to queue 79 | func (q *Queue) Stop() { 80 | q.Quit <- nil 81 | } 82 | 83 | // StopByError push stop request wth error to queue 84 | func (q *Queue) StopByError(err error) { 85 | q.Quit <- err 86 | } 87 | 88 | //--------------------------------------------------------- 89 | // Logging functions 90 | //--------------------------------------------------------- 91 | 92 | // PushTrace push message to trace-log queue 93 | func (q *Queue) PushTrace(msg string) { 94 | q.Logs.Trace <- msg 95 | } 96 | 97 | // PushInfo push message to info-log queue 98 | func (q *Queue) PushInfo(msg string) { 99 | q.Logs.Info <- msg 100 | } 101 | 102 | // PushWarn push message to warn-log queue 103 | func (q *Queue) PushWarn(err error) { 104 | q.Logs.Warn <- err 105 | } 106 | 107 | // PushError push error to error queue 108 | func (q *Queue) PushError(err error) { 109 | q.Logs.Error <- err 110 | } 111 | -------------------------------------------------------------------------------- /job/dispatcher.go: -------------------------------------------------------------------------------- 1 | package job 2 | 3 | import ( 4 | "github.com/sacloud/sackerel/job/core" 5 | "github.com/sacloud/sackerel/job/worker/timer" 6 | "log" 7 | "os" 8 | "time" 9 | ) 10 | 11 | // Dispatcher ジョブキューに対するディスパッチ処理を担当する 12 | type Dispatcher struct { 13 | option *core.Option 14 | queue *core.Queue 15 | timerJobs []core.TimerJobAPI 16 | } 17 | 18 | // NewDispatcher Dispatcherの新規作成 19 | func NewDispatcher(option *core.Option, queue *core.Queue) *Dispatcher { 20 | return &Dispatcher{ 21 | option: option, 22 | queue: queue, 23 | timerJobs: []core.TimerJobAPI{ 24 | timer.DetectResourceTimerJob(option.TimerJobInterval), 25 | timer.ReconcileHostTimerJob(option.ReconcileJobInterval), 26 | }, 27 | } 28 | } 29 | 30 | // Dispatch ジョブキューに対する各種ワーカーの登録やルーティング処理の登録、ディスパッチを行う 31 | func (d *Dispatcher) Dispatch() error { 32 | 33 | d.queue.PushInfo(" ***** Start sackerel ***** ") 34 | 35 | // エラー時処理 登録 36 | d.dispatchMessageAction() 37 | 38 | // ジョブのルーティング 登録 39 | d.dispatchJobRequests() 40 | 41 | // API呼び出し 登録 42 | d.dispatchJobs() 43 | 44 | // 初期化用ジョブ起動 45 | d.dispatchInitJobs() 46 | 47 | // タイマーディスパッチ 登録 48 | d.dispatchTimerJobs() 49 | 50 | // 終了待機 51 | err := <-d.queue.Quit 52 | return err 53 | } 54 | 55 | func (d *Dispatcher) dispatchInitJobs() { 56 | if d.option.SkipInit { 57 | return 58 | } 59 | d.queue.PushRequest("init", nil) 60 | } 61 | 62 | func (d *Dispatcher) dispatchMessageAction() { 63 | 64 | log.SetFlags(log.Ldate | log.Ltime) 65 | log.SetOutput(os.Stdout) 66 | out := log.Printf 67 | 68 | go func() { 69 | for { 70 | select { 71 | case msg := <-d.queue.Logs.Trace: 72 | if d.option.TraceLog { 73 | go out("[TRACE] %s\n", msg) 74 | } 75 | case msg := <-d.queue.Logs.Info: 76 | if d.option.InfoLog { 77 | go out("[INFO] %s\n", msg) 78 | } 79 | case err := <-d.queue.Logs.Warn: 80 | if d.option.WarnLog { 81 | go out("[WARN] %s\n", err) 82 | } 83 | case err := <-d.queue.Logs.Error: 84 | if d.option.ErrorLog { 85 | go out("[ERROR] %s\n", err) 86 | } 87 | } 88 | } 89 | }() 90 | } 91 | 92 | func (d *Dispatcher) dispatchJobRequests() { 93 | 94 | router := NewRouter(d.queue, d.option) 95 | 96 | go func() { 97 | for { 98 | select { 99 | case req := <-d.queue.Request: 100 | go router.Routing(req) 101 | } 102 | } 103 | }() 104 | } 105 | 106 | func (d *Dispatcher) dispatchJobs() { 107 | 108 | jobQueues := []chan core.JobAPI{ 109 | d.queue.SakuraRequest, 110 | d.queue.MackerelRequest, 111 | d.queue.Internal, 112 | } 113 | 114 | for _, jobQ := range jobQueues { 115 | q := jobQ 116 | go func() { 117 | for { 118 | select { 119 | case job := <-q: 120 | go job.Start(d.queue, d.option) 121 | } 122 | } 123 | }() 124 | } 125 | 126 | // スロットリングありキューは合間にインターバルを設けておく 127 | q := d.queue.ThrottledRequest 128 | go func() { 129 | for { 130 | select { 131 | case job := <-q: 132 | time.Sleep(d.option.APICallInterval) 133 | go job.Start(d.queue, d.option) 134 | } 135 | } 136 | }() 137 | 138 | } 139 | 140 | func (d *Dispatcher) dispatchTimerJobs() { 141 | for _, job := range d.timerJobs { 142 | t := time.NewTicker(job.GetTickerDuration()) 143 | j := job 144 | 145 | // 起動時に即時実行しておく 146 | go j.Start(d.queue, d.option) 147 | 148 | go func() { 149 | for { 150 | select { 151 | case <-t.C: 152 | go j.Start(d.queue, d.option) 153 | } 154 | } 155 | }() 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/auto_backup.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | // AutoBackup 自動バックアップ(CommonServiceItem) 10 | type AutoBackup struct { 11 | *Resource 12 | // Name 名称 13 | Name string 14 | // Description 説明 15 | Description string `json:",omitempty"` 16 | // Status ステータス 17 | Status *AutoBackupStatus `json:",omitempty"` 18 | // Provider プロバイダ 19 | Provider *AutoBackupProvider `json:",omitempty"` 20 | // Settings 設定 21 | Settings *AutoBackupSettings `json:",omitempty"` 22 | // ServiceClass サービスクラス 23 | ServiceClass string `json:",omitempty"` 24 | // CreatedAt 作成日時 25 | CreatedAt *time.Time `json:",omitempty"` 26 | // ModifiedAt 変更日時 27 | ModifiedAt *time.Time `json:",omitempty"` 28 | // Icon アイコン 29 | Icon *Icon `json:",omitempty"` 30 | *TagsType 31 | } 32 | 33 | // AutoBackupSettings 自動バックアップ設定 34 | type AutoBackupSettings struct { 35 | // AccountID アカウントID 36 | AccountID json.Number `json:"AccountId,omitempty"` 37 | // DiskID ディスクID 38 | DiskID string `json:"DiskId,omitempty"` 39 | // ZoneID ゾーンID 40 | ZoneID int64 `json:"ZoneId,omitempty"` 41 | // ZoneName ゾーン名称 42 | ZoneName string `json:",omitempty"` 43 | // Autobackup 自動バックアップ定義 44 | Autobackup *AutoBackupRecordSets `json:",omitempty"` 45 | } 46 | 47 | // AutoBackupStatus 自動バックアップステータス 48 | type AutoBackupStatus struct { 49 | // AccountID アカウントID 50 | AccountID json.Number `json:"AccountId,omitempty"` 51 | // DiskID ディスクID 52 | DiskID string `json:"DiskId,omitempty"` 53 | // ZoneID ゾーンID 54 | ZoneID int64 `json:"ZoneId,omitempty"` 55 | // ZoneName ゾーン名称 56 | ZoneName string `json:",omitempty"` 57 | } 58 | 59 | // AutoBackupProvider 自動バックアッププロバイダ 60 | type AutoBackupProvider struct { 61 | // Class クラス 62 | Class string `json:",omitempty"` 63 | } 64 | 65 | // CreateNewAutoBackup 自動バックアップ 作成(CommonServiceItem) 66 | func CreateNewAutoBackup(backupName string, diskID int64) *AutoBackup { 67 | return &AutoBackup{ 68 | Resource: &Resource{}, 69 | Name: backupName, 70 | Status: &AutoBackupStatus{ 71 | DiskID: fmt.Sprintf("%d", diskID), 72 | }, 73 | Provider: &AutoBackupProvider{ 74 | Class: "autobackup", 75 | }, 76 | Settings: &AutoBackupSettings{ 77 | Autobackup: &AutoBackupRecordSets{ 78 | BackupSpanType: "weekdays", 79 | }, 80 | }, 81 | TagsType: &TagsType{}, 82 | } 83 | } 84 | 85 | // AllowAutoBackupWeekdays 自動バックアップ実行曜日リスト 86 | func AllowAutoBackupWeekdays() []string { 87 | return []string{"mon", "tue", "wed", "thu", "fri", "sat", "sun"} 88 | } 89 | 90 | // AllowAutoBackupHour 自動バックアップ実行開始時間リスト 91 | func AllowAutoBackupHour() []int { 92 | return []int{0, 6, 12, 18} 93 | } 94 | 95 | // AutoBackupRecordSets 自動バックアップ定義 96 | type AutoBackupRecordSets struct { 97 | // BackupSpanType バックアップ間隔タイプ 98 | BackupSpanType string 99 | // BackupHour バックアップ開始時間 100 | BackupHour int 101 | // BackupSpanWeekdays バックアップ実施曜日 102 | BackupSpanWeekdays []string 103 | // MaximumNumberOfArchives 世代数 104 | MaximumNumberOfArchives int 105 | } 106 | 107 | // SetBackupHour バックアップ開始時間設定 108 | func (a *AutoBackup) SetBackupHour(hour int) { 109 | a.Settings.Autobackup.BackupHour = hour 110 | } 111 | 112 | // SetBackupSpanWeekdays バックアップ実行曜日設定 113 | func (a *AutoBackup) SetBackupSpanWeekdays(weekdays []string) { 114 | a.Settings.Autobackup.BackupSpanWeekdays = weekdays 115 | } 116 | 117 | // SetBackupMaximumNumberOfArchives 世代数設定 118 | func (a *AutoBackup) SetBackupMaximumNumberOfArchives(max int) { 119 | a.Settings.Autobackup.MaximumNumberOfArchives = max 120 | } 121 | -------------------------------------------------------------------------------- /vendor/github.com/mackerelio/mackerel-client-go/dashboards.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | ) 8 | 9 | /* 10 | { 11 | "dashboards": [ 12 | { 13 | "id": "2c5bLca8d", 14 | "title": "My Dashboard", 15 | "bodyMarkdown": "# A test dashboard", 16 | "urlPath": "2u4PP3TJqbu", 17 | "createdAt": 1439346145003, 18 | "updatedAt": 1439346145003 19 | } 20 | ] 21 | } 22 | */ 23 | 24 | // Dashboard information 25 | type Dashboard struct { 26 | ID string `json:"id,omitempty"` 27 | Title string `json:"title,omitempty"` 28 | BodyMarkDown string `json:"bodyMarkdown,omitempty"` 29 | URLPath string `json:"urlPath,omitempty"` 30 | CreatedAt int64 `json:"createdAt,omitempty"` 31 | UpdatedAt int64 `json:"updatedAt,omitempty"` 32 | } 33 | 34 | // FindDashboards find dashboards 35 | func (c *Client) FindDashboards() ([]*Dashboard, error) { 36 | req, err := http.NewRequest("GET", c.urlFor("/api/v0/dashboards").String(), nil) 37 | if err != nil { 38 | return nil, err 39 | } 40 | resp, err := c.Request(req) 41 | defer closeResponse(resp) 42 | if err != nil { 43 | return nil, err 44 | } 45 | 46 | var data struct { 47 | Dashboards []*(Dashboard) `json:"dashboards"` 48 | } 49 | err = json.NewDecoder(resp.Body).Decode(&data) 50 | if err != nil { 51 | return nil, err 52 | } 53 | 54 | return data.Dashboards, err 55 | } 56 | 57 | // FindDashboard find dashboard 58 | func (c *Client) FindDashboard(dashboardID string) (*Dashboard, error) { 59 | req, err := http.NewRequest("GET", c.urlFor(fmt.Sprintf("/api/v0/dashboards/%s", dashboardID)).String(), nil) 60 | if err != nil { 61 | return nil, err 62 | } 63 | resp, err := c.Request(req) 64 | defer closeResponse(resp) 65 | if err != nil { 66 | return nil, err 67 | } 68 | 69 | var data Dashboard 70 | err = json.NewDecoder(resp.Body).Decode(&data) 71 | if err != nil { 72 | return nil, err 73 | } 74 | return &data, err 75 | } 76 | 77 | // CreateDashboard creating dashboard 78 | func (c *Client) CreateDashboard(param *Dashboard) (*Dashboard, error) { 79 | resp, err := c.PostJSON("/api/v0/dashboards", param) 80 | defer closeResponse(resp) 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | var data Dashboard 86 | err = json.NewDecoder(resp.Body).Decode(&data) 87 | if err != nil { 88 | return nil, err 89 | } 90 | return &data, nil 91 | } 92 | 93 | // UpdateDashboard update dashboard 94 | func (c *Client) UpdateDashboard(dashboardID string, param *Dashboard) (*Dashboard, error) { 95 | resp, err := c.PutJSON(fmt.Sprintf("/api/v0/dashboards/%s", dashboardID), param) 96 | defer closeResponse(resp) 97 | if err != nil { 98 | return nil, err 99 | } 100 | 101 | var data Dashboard 102 | err = json.NewDecoder(resp.Body).Decode(&data) 103 | if err != nil { 104 | return nil, err 105 | } 106 | return &data, nil 107 | } 108 | 109 | // DeleteDashboard delete dashboard 110 | func (c *Client) DeleteDashboard(dashboardID string) (*Dashboard, error) { 111 | req, err := http.NewRequest( 112 | "DELETE", 113 | c.urlFor(fmt.Sprintf("/api/v0/dashboards/%s", dashboardID)).String(), 114 | nil, 115 | ) 116 | if err != nil { 117 | return nil, err 118 | } 119 | req.Header.Add("Content-Type", "application/json") 120 | 121 | resp, err := c.Request(req) 122 | defer closeResponse(resp) 123 | if err != nil { 124 | return nil, err 125 | } 126 | 127 | var data Dashboard 128 | err = json.NewDecoder(resp.Body).Decode(&data) 129 | if err != nil { 130 | return nil, err 131 | } 132 | return &data, nil 133 | } 134 | -------------------------------------------------------------------------------- /vendor/github.com/mackerelio/mackerel-client-go/mackerel.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "log" 8 | "net/http" 9 | "net/http/httputil" 10 | "net/url" 11 | "time" 12 | ) 13 | 14 | const ( 15 | defaultBaseURL = "https://mackerel.io/api/v0" 16 | defaultUserAgent = "mackerel-client-go" 17 | apiRequestTimeout = 30 * time.Second 18 | ) 19 | 20 | // Client api client for mackerel 21 | type Client struct { 22 | BaseURL *url.URL 23 | APIKey string 24 | Verbose bool 25 | UserAgent string 26 | AdditionalHeaders http.Header 27 | } 28 | 29 | func init() { 30 | log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) 31 | } 32 | 33 | // NewClient returns new mackerel.Client 34 | func NewClient(apikey string) *Client { 35 | u, _ := url.Parse(defaultBaseURL) 36 | return &Client{u, apikey, false, defaultUserAgent, http.Header{}} 37 | } 38 | 39 | // NewClientWithOptions returns new mackerel.Client 40 | func NewClientWithOptions(apikey string, rawurl string, verbose bool) (*Client, error) { 41 | u, err := url.Parse(rawurl) 42 | if err != nil { 43 | return nil, err 44 | } 45 | return &Client{u, apikey, verbose, defaultUserAgent, http.Header{}}, nil 46 | } 47 | 48 | func (c *Client) urlFor(path string) *url.URL { 49 | newURL, err := url.Parse(c.BaseURL.String()) 50 | if err != nil { 51 | panic("invalid url passed") 52 | } 53 | 54 | newURL.Path = path 55 | 56 | return newURL 57 | } 58 | 59 | func (c *Client) buildReq(req *http.Request) *http.Request { 60 | for header, values := range c.AdditionalHeaders { 61 | for _, v := range values { 62 | req.Header.Add(header, v) 63 | } 64 | } 65 | req.Header.Set("X-Api-Key", c.APIKey) 66 | req.Header.Set("User-Agent", c.UserAgent) 67 | return req 68 | } 69 | 70 | // Request request to mackerel and receive response 71 | func (c *Client) Request(req *http.Request) (resp *http.Response, err error) { 72 | req = c.buildReq(req) 73 | 74 | if c.Verbose { 75 | dump, err := httputil.DumpRequest(req, true) 76 | if err == nil { 77 | log.Printf("%s", dump) 78 | } 79 | } 80 | 81 | client := &http.Client{} // same as http.DefaultClient 82 | client.Timeout = apiRequestTimeout 83 | resp, err = client.Do(req) 84 | if err != nil { 85 | return nil, err 86 | } 87 | if c.Verbose { 88 | dump, err := httputil.DumpResponse(resp, true) 89 | if err == nil { 90 | log.Printf("%s", dump) 91 | } 92 | } 93 | if resp.StatusCode < 200 || resp.StatusCode > 299 { 94 | return resp, fmt.Errorf("API result failed: %s", resp.Status) 95 | } 96 | return resp, nil 97 | } 98 | 99 | // PostJSON shortcut method for posting json 100 | func (c *Client) PostJSON(path string, payload interface{}) (*http.Response, error) { 101 | return c.requestJSON("POST", path, payload) 102 | } 103 | 104 | // PutJSON shortcut method for putting json 105 | func (c *Client) PutJSON(path string, payload interface{}) (*http.Response, error) { 106 | return c.requestJSON("PUT", path, payload) 107 | } 108 | 109 | func (c *Client) requestJSON(method string, path string, payload interface{}) (*http.Response, error) { 110 | var body bytes.Buffer 111 | err := json.NewEncoder(&body).Encode(payload) 112 | if err != nil { 113 | return nil, err 114 | } 115 | 116 | req, err := http.NewRequest(method, c.urlFor(path).String(), &body) 117 | if err != nil { 118 | return nil, err 119 | } 120 | req.Header.Add("Content-Type", "application/json") 121 | return c.Request(req) 122 | } 123 | 124 | func closeResponse(resp *http.Response) { 125 | if resp != nil { 126 | resp.Body.Close() 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/vpc_router.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | // VPCRouter VPCルーター 4 | type VPCRouter struct { 5 | *Appliance 6 | // Remark リマーク 7 | Remark *VPCRouterRemark `json:",omitempty"` 8 | // Settings VPCルーター設定リスト 9 | Settings *VPCRouterSettings `json:",omitempty"` 10 | } 11 | 12 | // VPCRouterRemark リマーク 13 | type VPCRouterRemark struct { 14 | *ApplianceRemarkBase 15 | // TODO Zone 16 | //Zone *Resource 17 | } 18 | 19 | // VPCRouterSettings VPCルーター設定リスト 20 | type VPCRouterSettings struct { 21 | // Router VPCルーター設定 22 | Router *VPCRouterSetting `json:",omitempty"` 23 | } 24 | 25 | // CreateNewVPCRouter VPCルーター作成 26 | func CreateNewVPCRouter() *VPCRouter { 27 | return &VPCRouter{ 28 | Appliance: &Appliance{ 29 | Class: "vpcrouter", 30 | Plan: &Resource{}, 31 | TagsType: &TagsType{}, 32 | }, 33 | Remark: &VPCRouterRemark{ 34 | ApplianceRemarkBase: &ApplianceRemarkBase{ 35 | Servers: []interface{}{""}, 36 | Switch: &ApplianceRemarkSwitch{}, 37 | }, 38 | }, 39 | Settings: &VPCRouterSettings{ 40 | Router: &VPCRouterSetting{}, 41 | }, 42 | } 43 | } 44 | 45 | // InitVPCRouterSetting VPCルーター設定初期化 46 | func (v *VPCRouter) InitVPCRouterSetting() { 47 | settings := &VPCRouterSettings{ 48 | Router: &VPCRouterSetting{}, 49 | } 50 | 51 | if v.Settings != nil && v.Settings.Router != nil && v.Settings.Router.Interfaces != nil { 52 | settings.Router.Interfaces = v.Settings.Router.Interfaces 53 | } 54 | if v.Settings != nil && v.Settings.Router != nil && v.Settings.Router.VRID != nil { 55 | settings.Router.VRID = v.Settings.Router.VRID 56 | } 57 | 58 | v.Settings = settings 59 | } 60 | 61 | // IsStandardPlan スタンダードプランか判定 62 | func (v *VPCRouter) IsStandardPlan() bool { 63 | return v.Plan.ID == 1 64 | } 65 | 66 | // IsPremiumPlan プレミアうプランか判定 67 | func (v *VPCRouter) IsPremiumPlan() bool { 68 | return v.Plan.ID == 2 69 | } 70 | 71 | // IsHighSpecPlan ハイスペックプランか判定 72 | func (v *VPCRouter) IsHighSpecPlan() bool { 73 | return v.Plan.ID == 3 74 | } 75 | 76 | // SetStandardPlan スタンダードプランへ設定 77 | func (v *VPCRouter) SetStandardPlan() { 78 | v.Plan.SetID(1) 79 | v.Remark.Switch = &ApplianceRemarkSwitch{ 80 | // Scope 81 | Scope: "shared", 82 | } 83 | v.Settings = nil 84 | } 85 | 86 | // SetPremiumPlan プレミアムプランへ設定 87 | func (v *VPCRouter) SetPremiumPlan(switchID string, virtualIPAddress string, ipAddress1 string, ipAddress2 string, vrid int, ipAliases []string) { 88 | v.Plan.SetID(2) 89 | v.setPremiumServices(switchID, virtualIPAddress, ipAddress1, ipAddress2, vrid, ipAliases) 90 | } 91 | 92 | // SetHighSpecPlan ハイスペックプランへ設定 93 | func (v *VPCRouter) SetHighSpecPlan(switchID string, virtualIPAddress string, ipAddress1 string, ipAddress2 string, vrid int, ipAliases []string) { 94 | v.Plan.SetID(3) 95 | v.setPremiumServices(switchID, virtualIPAddress, ipAddress1, ipAddress2, vrid, ipAliases) 96 | } 97 | 98 | func (v *VPCRouter) setPremiumServices(switchID string, virtualIPAddress string, ipAddress1 string, ipAddress2 string, vrid int, ipAliases []string) { 99 | v.Remark.Switch = &ApplianceRemarkSwitch{ 100 | ID: switchID, 101 | } 102 | v.Remark.Servers = []interface{}{ 103 | map[string]string{"IPAddress": ipAddress1}, 104 | map[string]string{"IPAddress": ipAddress2}, 105 | } 106 | 107 | v.Settings = &VPCRouterSettings{ 108 | Router: &VPCRouterSetting{ 109 | Interfaces: []*VPCRouterInterface{ 110 | { 111 | IPAddress: []string{ 112 | ipAddress1, 113 | ipAddress2, 114 | }, 115 | VirtualIPAddress: virtualIPAddress, 116 | IPAliases: ipAliases, 117 | }, 118 | }, 119 | VRID: &vrid, 120 | }, 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/auto_backup.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | // "strings" 6 | "github.com/sacloud/libsacloud/sacloud" 7 | ) 8 | 9 | // SearchAutoBackupResponse 自動バックアップ 検索レスポンス 10 | type SearchAutoBackupResponse struct { 11 | // Total 総件数 12 | Total int `json:",omitempty"` 13 | // From ページング開始位置 14 | From int `json:",omitempty"` 15 | // Count 件数 16 | Count int `json:",omitempty"` 17 | // CommonServiceAutoBackupItems 自動バックアップ リスト 18 | CommonServiceAutoBackupItems []sacloud.AutoBackup `json:"CommonServiceItems,omitempty"` 19 | } 20 | 21 | type autoBackupRequest struct { 22 | CommonServiceAutoBackupItem *sacloud.AutoBackup `json:"CommonServiceItem,omitempty"` 23 | From int `json:",omitempty"` 24 | Count int `json:",omitempty"` 25 | Sort []string `json:",omitempty"` 26 | Filter map[string]interface{} `json:",omitempty"` 27 | Exclude []string `json:",omitempty"` 28 | Include []string `json:",omitempty"` 29 | } 30 | 31 | type autoBackupResponse struct { 32 | *sacloud.ResultFlagValue 33 | *sacloud.AutoBackup `json:"CommonServiceItem,omitempty"` 34 | } 35 | 36 | // AutoBackupAPI 自動バックアップAPI 37 | type AutoBackupAPI struct { 38 | *baseAPI 39 | } 40 | 41 | // NewAutoBackupAPI 自動バックアップAPI作成 42 | func NewAutoBackupAPI(client *Client) *AutoBackupAPI { 43 | return &AutoBackupAPI{ 44 | &baseAPI{ 45 | client: client, 46 | FuncGetResourceURL: func() string { 47 | return "commonserviceitem" 48 | }, 49 | FuncBaseSearchCondition: func() *sacloud.Request { 50 | res := &sacloud.Request{} 51 | res.AddFilter("Provider.Class", "autobackup") 52 | return res 53 | }, 54 | }, 55 | } 56 | } 57 | 58 | // Find 検索 59 | func (api *AutoBackupAPI) Find() (*SearchAutoBackupResponse, error) { 60 | 61 | data, err := api.client.newRequest("GET", api.getResourceURL(), api.getSearchState()) 62 | if err != nil { 63 | return nil, err 64 | } 65 | var res SearchAutoBackupResponse 66 | if err := json.Unmarshal(data, &res); err != nil { 67 | return nil, err 68 | } 69 | return &res, nil 70 | } 71 | 72 | func (api *AutoBackupAPI) request(f func(*autoBackupResponse) error) (*sacloud.AutoBackup, error) { 73 | res := &autoBackupResponse{} 74 | err := f(res) 75 | if err != nil { 76 | return nil, err 77 | } 78 | return res.AutoBackup, nil 79 | } 80 | 81 | func (api *AutoBackupAPI) createRequest(value *sacloud.AutoBackup) *autoBackupResponse { 82 | return &autoBackupResponse{AutoBackup: value} 83 | } 84 | 85 | // New 新規作成用パラメーター作成 86 | func (api *AutoBackupAPI) New(name string, diskID int64) *sacloud.AutoBackup { 87 | return sacloud.CreateNewAutoBackup(name, diskID) 88 | } 89 | 90 | // Create 新規作成 91 | func (api *AutoBackupAPI) Create(value *sacloud.AutoBackup) (*sacloud.AutoBackup, error) { 92 | return api.request(func(res *autoBackupResponse) error { 93 | return api.create(api.createRequest(value), res) 94 | }) 95 | } 96 | 97 | // Read 読み取り 98 | func (api *AutoBackupAPI) Read(id int64) (*sacloud.AutoBackup, error) { 99 | return api.request(func(res *autoBackupResponse) error { 100 | return api.read(id, nil, res) 101 | }) 102 | } 103 | 104 | // Update 更新 105 | func (api *AutoBackupAPI) Update(id int64, value *sacloud.AutoBackup) (*sacloud.AutoBackup, error) { 106 | return api.request(func(res *autoBackupResponse) error { 107 | return api.update(id, api.createRequest(value), res) 108 | }) 109 | } 110 | 111 | // Delete 削除 112 | func (api *AutoBackupAPI) Delete(id int64) (*sacloud.AutoBackup, error) { 113 | return api.request(func(res *autoBackupResponse) error { 114 | return api.delete(id, nil, res) 115 | }) 116 | } 117 | -------------------------------------------------------------------------------- /job/worker/mackerel/regist_graph_defs.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | mkr "github.com/mackerelio/mackerel-client-go" 5 | "github.com/sacloud/sackerel/job/core" 6 | ) 7 | 8 | var ( 9 | cpuCustomGraph = &mkr.GraphDefsParam{ 10 | Name: "custom.sacloud.cpu.#", 11 | DisplayName: "CPU", 12 | Unit: "percentage", 13 | Metrics: []*mkr.GraphDefsMetric{ 14 | { 15 | Name: "custom.sacloud.cpu.#.cpu-time", 16 | DisplayName: "CPU Time", 17 | IsStacked: false, 18 | }, 19 | }, 20 | } 21 | 22 | diskCustomGraph = &mkr.GraphDefsParam{ 23 | Name: "custom.sacloud.disk.#", 24 | DisplayName: "Disk", 25 | Unit: "bytes/sec", 26 | Metrics: []*mkr.GraphDefsMetric{ 27 | { 28 | Name: "custom.sacloud.disk.#.read", 29 | DisplayName: "Read bytes", 30 | IsStacked: false, 31 | }, 32 | { 33 | Name: "custom.sacloud.disk.#.write", 34 | DisplayName: "Write bytes", 35 | IsStacked: false, 36 | }, 37 | }, 38 | } 39 | 40 | interfaceCustomGraph = &mkr.GraphDefsParam{ 41 | Name: "custom.sacloud.interface.#", 42 | DisplayName: "Interface", 43 | Unit: "bytes/sec", 44 | Metrics: []*mkr.GraphDefsMetric{ 45 | { 46 | Name: "custom.sacloud.interface.#.send", 47 | DisplayName: "Send bytes", 48 | IsStacked: false, 49 | }, 50 | { 51 | Name: "custom.sacloud.interface.#.receive", 52 | DisplayName: "Receive bytes", 53 | IsStacked: false, 54 | }, 55 | }, 56 | } 57 | 58 | memorySizeCustomGraph = &mkr.GraphDefsParam{ 59 | Name: "custom.sacloud.memorysize.#", 60 | DisplayName: "Memory Size", 61 | Unit: "bytes", 62 | Metrics: []*mkr.GraphDefsMetric{ 63 | { 64 | Name: "custom.sacloud.memorysize.#.total", 65 | DisplayName: "Total memory bytes", 66 | IsStacked: false, 67 | }, 68 | { 69 | Name: "custom.sacloud.memorysize.#.used", 70 | DisplayName: "Used memory bytes", 71 | IsStacked: false, 72 | }, 73 | }, 74 | } 75 | diskSizeBackupCustomGraph = &mkr.GraphDefsParam{ 76 | Name: "custom.sacloud.disksize.backup.#", 77 | DisplayName: "Disk Size(Backup)", 78 | Unit: "bytes", 79 | Metrics: []*mkr.GraphDefsMetric{ 80 | { 81 | Name: "custom.sacloud.disksize.backup.#.total", 82 | DisplayName: "Total disk bytes", 83 | IsStacked: false, 84 | }, 85 | { 86 | Name: "custom.sacloud.disksize.backup.#.used", 87 | DisplayName: "Used disk bytes", 88 | IsStacked: false, 89 | }, 90 | }, 91 | } 92 | diskSizeSystemCustomGraph = &mkr.GraphDefsParam{ 93 | Name: "custom.sacloud.disksize.system.#", 94 | DisplayName: "Disk Size(System)", 95 | Unit: "bytes", 96 | Metrics: []*mkr.GraphDefsMetric{ 97 | { 98 | Name: "custom.sacloud.disksize.system.#.total", 99 | DisplayName: "Total disk bytes", 100 | IsStacked: false, 101 | }, 102 | { 103 | Name: "custom.sacloud.disksize.system.#.used", 104 | DisplayName: "Used disk bytes", 105 | IsStacked: false, 106 | }, 107 | }, 108 | } 109 | ) 110 | 111 | // RegistGraphDefsJob Mackerelのカスタムグラフ登録用ジョブ 112 | func RegistGraphDefsJob(payload interface{}) core.JobAPI { 113 | return core.NewJob("MackerelRegistGraphDefs", registGraphDefs, payload) 114 | } 115 | 116 | func registGraphDefs(queue *core.Queue, option *core.Option, job core.JobAPI) { 117 | 118 | client := getClient(option) 119 | 120 | err := client.CreateGraphDefs([]*mkr.GraphDefsParam{ 121 | cpuCustomGraph, 122 | diskCustomGraph, 123 | interfaceCustomGraph, 124 | memorySizeCustomGraph, 125 | diskSizeBackupCustomGraph, 126 | diskSizeSystemCustomGraph, 127 | }) 128 | 129 | if err != nil { 130 | queue.PushError(err) 131 | } 132 | 133 | queue.PushInfo("Initialized custom graph defines") 134 | } 135 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/api/simple_monitor.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | // "strings" 6 | "github.com/sacloud/libsacloud/sacloud" 7 | ) 8 | 9 | //HACK: さくらのAPI側仕様: CommonServiceItemsの内容によってJSONフォーマットが異なるため 10 | // DNS/GSLB/シンプル監視それぞれでリクエスト/レスポンスデータ型を定義する。 11 | 12 | // SearchSimpleMonitorResponse シンプル監視検索レスポンス 13 | type SearchSimpleMonitorResponse struct { 14 | // Total 総件数 15 | Total int `json:",omitempty"` 16 | // From ページング開始位置 17 | From int `json:",omitempty"` 18 | // Count 件数 19 | Count int `json:",omitempty"` 20 | // SimpleMonitors シンプル監視 リスト 21 | SimpleMonitors []sacloud.SimpleMonitor `json:"CommonServiceItems,omitempty"` 22 | } 23 | 24 | type simpleMonitorRequest struct { 25 | SimpleMonitor *sacloud.SimpleMonitor `json:"CommonServiceItem,omitempty"` 26 | From int `json:",omitempty"` 27 | Count int `json:",omitempty"` 28 | Sort []string `json:",omitempty"` 29 | Filter map[string]interface{} `json:",omitempty"` 30 | Exclude []string `json:",omitempty"` 31 | Include []string `json:",omitempty"` 32 | } 33 | 34 | type simpleMonitorResponse struct { 35 | *sacloud.ResultFlagValue 36 | *sacloud.SimpleMonitor `json:"CommonServiceItem,omitempty"` 37 | } 38 | 39 | // SimpleMonitorAPI シンプル監視API 40 | type SimpleMonitorAPI struct { 41 | *baseAPI 42 | } 43 | 44 | // NewSimpleMonitorAPI シンプル監視API作成 45 | func NewSimpleMonitorAPI(client *Client) *SimpleMonitorAPI { 46 | return &SimpleMonitorAPI{ 47 | &baseAPI{ 48 | client: client, 49 | FuncGetResourceURL: func() string { 50 | return "commonserviceitem" 51 | }, 52 | FuncBaseSearchCondition: func() *sacloud.Request { 53 | res := &sacloud.Request{} 54 | res.AddFilter("Provider.Class", "simplemon") 55 | return res 56 | }, 57 | }, 58 | } 59 | } 60 | 61 | // Find 検索 62 | func (api *SimpleMonitorAPI) Find() (*SearchSimpleMonitorResponse, error) { 63 | data, err := api.client.newRequest("GET", api.getResourceURL(), api.getSearchState()) 64 | if err != nil { 65 | return nil, err 66 | } 67 | var res SearchSimpleMonitorResponse 68 | if err := json.Unmarshal(data, &res); err != nil { 69 | return nil, err 70 | } 71 | return &res, nil 72 | } 73 | 74 | func (api *SimpleMonitorAPI) request(f func(*simpleMonitorResponse) error) (*sacloud.SimpleMonitor, error) { 75 | res := &simpleMonitorResponse{} 76 | err := f(res) 77 | if err != nil { 78 | return nil, err 79 | } 80 | return res.SimpleMonitor, nil 81 | } 82 | 83 | func (api *SimpleMonitorAPI) createRequest(value *sacloud.SimpleMonitor) *simpleMonitorResponse { 84 | return &simpleMonitorResponse{SimpleMonitor: value} 85 | } 86 | 87 | // New 新規作成用パラメーター作成 88 | func (api *SimpleMonitorAPI) New(target string) *sacloud.SimpleMonitor { 89 | return sacloud.CreateNewSimpleMonitor(target) 90 | } 91 | 92 | // Create 新規作成 93 | func (api *SimpleMonitorAPI) Create(value *sacloud.SimpleMonitor) (*sacloud.SimpleMonitor, error) { 94 | return api.request(func(res *simpleMonitorResponse) error { 95 | return api.create(api.createRequest(value), res) 96 | }) 97 | } 98 | 99 | // Read 読み取り 100 | func (api *SimpleMonitorAPI) Read(id int64) (*sacloud.SimpleMonitor, error) { 101 | return api.request(func(res *simpleMonitorResponse) error { 102 | return api.read(id, nil, res) 103 | }) 104 | } 105 | 106 | // Update 更新 107 | func (api *SimpleMonitorAPI) Update(id int64, value *sacloud.SimpleMonitor) (*sacloud.SimpleMonitor, error) { 108 | return api.request(func(res *simpleMonitorResponse) error { 109 | return api.update(id, api.createRequest(value), res) 110 | }) 111 | } 112 | 113 | // Delete 削除 114 | func (api *SimpleMonitorAPI) Delete(id int64) (*sacloud.SimpleMonitor, error) { 115 | return api.request(func(res *simpleMonitorResponse) error { 116 | return api.delete(id, nil, res) 117 | }) 118 | } 119 | -------------------------------------------------------------------------------- /job/worker/mackerel/functions.go: -------------------------------------------------------------------------------- 1 | package mackerel 2 | 3 | import ( 4 | "fmt" 5 | mkr "github.com/mackerelio/mackerel-client-go" 6 | "github.com/sacloud/sackerel/job/core" 7 | ) 8 | 9 | func getClient(option *core.Option) *mkr.Client { 10 | if option.MackerelOption.TraceMode { 11 | c, e := mkr.NewClientWithOptions(option.MackerelOption.APIKey, "https://mackerel.io/api/v0", true) 12 | if e != nil { 13 | panic(e) 14 | } 15 | c.UserAgent = "sackerel-trace-mode" 16 | return c 17 | } 18 | 19 | c := mkr.NewClient(option.MackerelOption.APIKey) 20 | c.UserAgent = "sackerel" 21 | return c 22 | 23 | } 24 | 25 | func findMackerelTarget(queue *core.Queue, option *core.Option, job core.JobAPI, resourceTypeName string) { 26 | 27 | var payload = job.GetPayload() 28 | if payload == nil { 29 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 30 | return 31 | } 32 | 33 | if findPayload, ok := payload.(core.MackerelFindParamHolder); ok { 34 | findParam := findPayload.GetFindParam() 35 | if findParam == nil { 36 | queue.PushWarn(fmt.Errorf("'%s' => payload is need FindParam", job.GetName())) 37 | return 38 | } 39 | 40 | // find from mackerel 41 | client := getClient(option) 42 | hosts, err := client.FindHosts(findParam) 43 | if err != nil { 44 | queue.PushError(err) 45 | return 46 | } 47 | 48 | if len(hosts) == 0 { 49 | queue.PushRequest("mackerel-not-found-"+resourceTypeName, payload) 50 | } else { 51 | for _, host := range hosts { 52 | 53 | //IDの設定 54 | if source, ok := payload.(core.SourcePayloadHolder); ok { 55 | mackerelInfo := source.GetSourcePayload() 56 | mackerelInfo.MackerelID = host.ID 57 | mackerelInfo.MackerelHost = host 58 | } 59 | 60 | queue.PushRequest("mackerel-found-"+resourceTypeName, payload) 61 | } 62 | } 63 | 64 | } else { 65 | 66 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [core.MackerelFindParamHolder]", job.GetName())) 67 | return 68 | } 69 | 70 | } 71 | 72 | func registMackerelTarget(queue *core.Queue, option *core.Option, job core.JobAPI, resourceTypeName string) { 73 | 74 | var payload = job.GetPayload() 75 | if payload == nil { 76 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 77 | return 78 | } 79 | 80 | if CreateHostPayload, ok := payload.(*core.CreateHostPayload); ok { 81 | createParam := CreateHostPayload.MackerelHostParam 82 | if createParam == nil { 83 | queue.PushWarn(fmt.Errorf("'%s' => payload is need CreateHostParam", job.GetName())) 84 | return 85 | } 86 | 87 | // create host in mackerel 88 | 89 | client := getClient(option) 90 | id, err := client.CreateHost(createParam) 91 | 92 | if err != nil { 93 | queue.PushError(err) 94 | return 95 | } 96 | 97 | targetName := fmt.Sprintf("(%s)", CreateHostPayload.SourceType.Name()) 98 | CreateHostPayload.MackerelID = id 99 | 100 | host, err := client.FindHost(id) 101 | if err != nil { 102 | queue.PushError(err) 103 | } 104 | if host == nil { 105 | queue.PushError(fmt.Errorf("Created host not found!")) 106 | return 107 | } 108 | CreateHostPayload.MackerelHost = host 109 | 110 | queue.PushInfo( 111 | fmt.Sprintf( 112 | "Host created %-15s => SakuraID:[%d] / MackerelID:[%s] / Name:[%s]", 113 | targetName, 114 | CreateHostPayload.SacloudResourceID, 115 | id, 116 | createParam.DisplayName, 117 | ), 118 | ) 119 | queue.PushRequest("mackerel-registed-"+resourceTypeName, payload) 120 | 121 | } else { 122 | 123 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [core.CreateHostPayload]", job.GetName())) 124 | return 125 | } 126 | 127 | } 128 | 129 | func hasSakuraCloudTag(target interface{}, targetTag string) bool { 130 | 131 | if tagsType, ok := target.(tagsHolder); ok { 132 | if tagsType.HasTag(targetTag) { 133 | return true 134 | } 135 | } 136 | 137 | return false 138 | } 139 | 140 | type tagsHolder interface { 141 | HasTag(string) bool 142 | } 143 | -------------------------------------------------------------------------------- /job/worker/sacloud/collect_database_metrics.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "fmt" 5 | "github.com/sacloud/libsacloud/sacloud" 6 | "github.com/sacloud/sackerel/job/core" 7 | "time" 8 | ) 9 | 10 | // CollectDatabaseMetricsAllJob 過去分含めたデータベースメトリクス(cpu/memory/interface/disk)を取得するジョブ 11 | func CollectDatabaseMetricsAllJob(payload interface{}) core.JobAPI { 12 | return core.NewJob("CollectMetricsDatabaseAll", collectDatabaseMetricsAll, payload) 13 | } 14 | 15 | // CollectDatabaseMetricsLatestJob 直近のデータベースメトリクス(Interface)を取得するジョブ 16 | func CollectDatabaseMetricsLatestJob(payload interface{}) core.JobAPI { 17 | return core.NewJob("CollectMetricsDatabaseLatest", collectDatabaseMetricsLatest, payload) 18 | } 19 | 20 | func collectDatabaseMetricsAll(queue *core.Queue, option *core.Option, job core.JobAPI) { 21 | collectDatabaseMetricsInner(queue, option, job, nil) 22 | } 23 | 24 | func collectDatabaseMetricsLatest(queue *core.Queue, option *core.Option, job core.JobAPI) { 25 | 26 | end := time.Now() 27 | start := end.Add(-option.MetricsHistoryPeriod) 28 | req := sacloud.NewResourceMonitorRequest(&start, &end) 29 | collectDatabaseMetricsInner(queue, option, job, req) 30 | } 31 | 32 | func collectDatabaseMetricsInner(queue *core.Queue, option *core.Option, job core.JobAPI, req *sacloud.ResourceMonitorRequest) { 33 | var payload = job.GetPayload() 34 | if payload == nil { 35 | queue.PushWarn(fmt.Errorf("'%s' => payload is nil", job.GetName())) 36 | return 37 | } 38 | 39 | // check payload types 40 | var sourcePayload *core.SourcePayload 41 | 42 | if s, ok := payload.(core.SourcePayloadHolder); ok { 43 | sourcePayload = s.GetSourcePayload() 44 | source := sourcePayload.SacloudSource 45 | if _, ok := source.(*sacloud.Database); !ok { 46 | queue.PushWarn(fmt.Errorf("'%s' => payload.Source is invalid type. need [*sacloud.Database]", job.GetName())) 47 | return 48 | } 49 | } else { 50 | queue.PushWarn(fmt.Errorf("'%s' => payload is invalid type. need [core.SourcePayloadHolder]", job.GetName())) 51 | return 52 | } 53 | 54 | if sourcePayload.MackerelHostStatus == core.MackerelHostStatusMaintenance { 55 | queue.PushWarn(fmt.Errorf("SakuraCloud resource['%d'] is still maintenance state. '%s' is skipped", sourcePayload.SacloudResourceID, job.GetName())) 56 | return 57 | } 58 | 59 | // Create the collect-metrics payload 60 | metricsPayload := core.NewCollectMetricsPayload(sourcePayload) 61 | client := getClient(option, sourcePayload.SacloudZone) 62 | 63 | //cpu 64 | cpuMetrics, err := client.Database.MonitorCPU(sourcePayload.SacloudResourceID, req) 65 | if err != nil { 66 | queue.PushError(err) 67 | return 68 | } 69 | metricsPayload.Metrics.CPU = append(metricsPayload.Metrics.CPU, cpuMetrics) 70 | 71 | // interfaces 72 | nicMetrics, err := client.Database.MonitorInterface(sourcePayload.SacloudResourceID, req) 73 | if err != nil { 74 | queue.PushError(err) 75 | return 76 | } 77 | metricsPayload.Metrics.Interface = append(metricsPayload.Metrics.Interface, nicMetrics) 78 | 79 | // Disk:System(Read/Write) 80 | systemDiskMetrics, err := client.Database.MonitorSystemDisk(sourcePayload.SacloudResourceID, req) 81 | if err != nil { 82 | queue.PushError(err) 83 | return 84 | } 85 | metricsPayload.Metrics.Disk = append(metricsPayload.Metrics.Interface, systemDiskMetrics) 86 | 87 | // Disk:Backup(Read/Write) 88 | backupDiskMetrics, err := client.Database.MonitorBackupDisk(sourcePayload.SacloudResourceID, req) 89 | if err != nil { 90 | queue.PushError(err) 91 | return 92 | } 93 | metricsPayload.Metrics.Disk = append(metricsPayload.Metrics.Interface, backupDiskMetrics) 94 | 95 | // Database(MemorySize , DiskSize[System/Backup]) 96 | databaseMetrics, err := client.Database.MonitorDatabase(sourcePayload.SacloudResourceID, req) 97 | if err != nil { 98 | queue.PushError(err) 99 | return 100 | } 101 | metricsPayload.Metrics.Database = append(metricsPayload.Metrics.Interface, databaseMetrics) 102 | 103 | queue.PushRequest("collected-database-metrics", metricsPayload) 104 | } 105 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/http_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "net/http/httptest" 7 | "net/url" 8 | "strings" 9 | ) 10 | 11 | // httpCode is a helper that returns HTTP code of the response. It returns -1 12 | // if building a new request fails. 13 | func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int { 14 | w := httptest.NewRecorder() 15 | req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) 16 | if err != nil { 17 | return -1 18 | } 19 | handler(w, req) 20 | return w.Code 21 | } 22 | 23 | // HTTPSuccess asserts that a specified handler returns a success status code. 24 | // 25 | // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) 26 | // 27 | // Returns whether the assertion was successful (true) or not (false). 28 | func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { 29 | code := httpCode(handler, method, url, values) 30 | if code == -1 { 31 | return false 32 | } 33 | return code >= http.StatusOK && code <= http.StatusPartialContent 34 | } 35 | 36 | // HTTPRedirect asserts that a specified handler returns a redirect status code. 37 | // 38 | // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} 39 | // 40 | // Returns whether the assertion was successful (true) or not (false). 41 | func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { 42 | code := httpCode(handler, method, url, values) 43 | if code == -1 { 44 | return false 45 | } 46 | return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect 47 | } 48 | 49 | // HTTPError asserts that a specified handler returns an error status code. 50 | // 51 | // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} 52 | // 53 | // Returns whether the assertion was successful (true) or not (false). 54 | func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { 55 | code := httpCode(handler, method, url, values) 56 | if code == -1 { 57 | return false 58 | } 59 | return code >= http.StatusBadRequest 60 | } 61 | 62 | // HTTPBody is a helper that returns HTTP body of the response. It returns 63 | // empty string if building a new request fails. 64 | func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { 65 | w := httptest.NewRecorder() 66 | req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) 67 | if err != nil { 68 | return "" 69 | } 70 | handler(w, req) 71 | return w.Body.String() 72 | } 73 | 74 | // HTTPBodyContains asserts that a specified handler returns a 75 | // body that contains a string. 76 | // 77 | // assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") 78 | // 79 | // Returns whether the assertion was successful (true) or not (false). 80 | func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool { 81 | body := HTTPBody(handler, method, url, values) 82 | 83 | contains := strings.Contains(body, fmt.Sprint(str)) 84 | if !contains { 85 | Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) 86 | } 87 | 88 | return contains 89 | } 90 | 91 | // HTTPBodyNotContains asserts that a specified handler returns a 92 | // body that does not contain a string. 93 | // 94 | // assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") 95 | // 96 | // Returns whether the assertion was successful (true) or not (false). 97 | func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool { 98 | body := HTTPBody(handler, method, url, values) 99 | 100 | contains := strings.Contains(body, fmt.Sprint(str)) 101 | if contains { 102 | Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body) 103 | } 104 | 105 | return !contains 106 | } 107 | -------------------------------------------------------------------------------- /vendor/github.com/sacloud/libsacloud/sacloud/server.go: -------------------------------------------------------------------------------- 1 | package sacloud 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // Server サーバー 8 | type Server struct { 9 | *Resource 10 | // Name 名称 11 | Name string 12 | // HostName (初期)ホスト名 13 | // 14 | // ディスクの修正実施時に指定したホスト名 15 | HostName string `json:",omitempty"` 16 | // Description 説明 17 | Description string `json:",omitempty"` 18 | *EAvailability 19 | // ServiceClass サービスクラス 20 | ServiceClass string `json:",omitempty"` 21 | // CreatedAt 作成日時 22 | CreatedAt *time.Time `json:",omitempty"` 23 | // Icon アイコン 24 | Icon *Resource `json:",omitempty"` 25 | // ServerPlan サーバープラン 26 | ServerPlan *ProductServer `json:",omitempty"` 27 | // Zone ゾーン 28 | Zone *Zone `json:",omitempty"` 29 | *TagsType 30 | // ConnectedSwitches サーバー作成時の接続先スイッチ指定用パラメーター 31 | ConnectedSwitches []interface{} `json:",omitempty" libsacloud:"requestOnly"` 32 | // Disks ディスク 33 | Disks []Disk `json:",omitempty"` 34 | // Interfaces インターフェース 35 | Interfaces []Interface `json:",omitempty"` 36 | // Instance インスタンス 37 | Instance *Instance `json:",omitempty"` 38 | } 39 | 40 | // SetServerPlanByID サーバープラン設定 41 | func (s *Server) SetServerPlanByID(planID string) { 42 | if s.ServerPlan == nil { 43 | s.ServerPlan = &ProductServer{Resource: NewResourceByStringID(planID)} 44 | } 45 | } 46 | 47 | // ClearConnectedSwitches 接続先スイッチ指定パラメータークリア 48 | func (s *Server) ClearConnectedSwitches() { 49 | s.ConnectedSwitches = []interface{}{} 50 | } 51 | 52 | // AddPublicNWConnectedParam 共有セグメントへ接続したNIC追加 53 | func (s *Server) AddPublicNWConnectedParam() { 54 | if s.ConnectedSwitches == nil { 55 | s.ClearConnectedSwitches() 56 | } 57 | s.ConnectedSwitches = append(s.ConnectedSwitches, map[string]interface{}{"Scope": "shared"}) 58 | } 59 | 60 | // AddExistsSwitchConnectedParam スイッチへ接続したNIC追加 61 | func (s *Server) AddExistsSwitchConnectedParam(switchID string) { 62 | if s.ConnectedSwitches == nil { 63 | s.ClearConnectedSwitches() 64 | } 65 | s.ConnectedSwitches = append(s.ConnectedSwitches, map[string]interface{}{"ID": switchID}) 66 | } 67 | 68 | // AddEmptyConnectedParam 未接続なNIC追加 69 | func (s *Server) AddEmptyConnectedParam() { 70 | if s.ConnectedSwitches == nil { 71 | s.ClearConnectedSwitches() 72 | } 73 | s.ConnectedSwitches = append(s.ConnectedSwitches, nil) 74 | } 75 | 76 | // GetDiskIDs ディスクID配列を返す 77 | func (s *Server) GetDiskIDs() []int64 { 78 | 79 | ids := []int64{} 80 | for _, disk := range s.Disks { 81 | ids = append(ids, disk.ID) 82 | } 83 | return ids 84 | 85 | } 86 | 87 | // KeyboardRequest キーボード送信リクエスト 88 | type KeyboardRequest struct { 89 | // Keys キー(複数) 90 | Keys []string `json:",omitempty"` 91 | // Key キー(単体) 92 | Key string `json:",omitempty"` 93 | } 94 | 95 | // MouseRequest マウス送信リクエスト 96 | type MouseRequest struct { 97 | // X X 98 | X *int `json:",omitempty"` 99 | // Y Y 100 | Y *int `json:",omitempty"` 101 | // Z Z 102 | Z *int `json:",omitempty"` 103 | // Buttons マウスボタン 104 | Buttons *MouseRequestButtons `json:",omitempty"` 105 | } 106 | 107 | // VNCSnapshotRequest VNCスナップショット取得リクエスト 108 | type VNCSnapshotRequest struct { 109 | // ScreenSaverExitTimeMS スクリーンセーバーからの復帰待ち時間 110 | ScreenSaverExitTimeMS int `json:",omitempty"` 111 | } 112 | 113 | // MouseRequestButtons マウスボタン 114 | type MouseRequestButtons struct { 115 | // L 左ボタン 116 | L bool `json:",omitempty"` 117 | // R 右ボタン 118 | R bool `json:",omitempty"` 119 | // M 中ボタン 120 | M bool `json:",omitempty"` 121 | } 122 | 123 | // VNCProxyResponse VNCプロキシ取得レスポンス 124 | type VNCProxyResponse struct { 125 | *ResultFlagValue 126 | // Status ステータス 127 | Status string `json:",omitempty"` 128 | // Host プロキシホスト 129 | Host string `json:",omitempty"` 130 | // Port ポート番号 131 | Port string `json:",omitempty"` 132 | // Password VNCパスワード 133 | Password string `json:",omitempty"` 134 | // VNCFile VNC接続情報ファイル(VNCビューア用) 135 | VNCFile string `json:",omitempty"` 136 | } 137 | 138 | // VNCSizeResponse VNC画面サイズレスポンス 139 | type VNCSizeResponse struct { 140 | // Width 幅 141 | Width int `json:",string,omitempty"` 142 | // Height 高さ 143 | Height int `json:",string,omitempty"` 144 | } 145 | 146 | // VNCSnapshotResponse VPCスナップショットレスポンス 147 | type VNCSnapshotResponse struct { 148 | // Image スナップショット画像データ 149 | Image string `json:",omitempty"` 150 | } 151 | --------------------------------------------------------------------------------