mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-20 09:39:08 +00:00
Merge pull request #3377 from Sh4d1/update_scaleway_provider
Update Scaleway Provider with new Go SDK
This commit is contained in:
commit
66cd2b6ee5
@ -78,6 +78,7 @@ Currently supported platforms are:
|
||||
- [Google Cloud](docs/platform-gcp.md) `[x86_64]`
|
||||
- [Microsoft Azure](docs/platform-azure.md) `[x86_64]`
|
||||
- [OpenStack](docs/platform-openstack.md) `[x86_64]`
|
||||
- [Scaleway](docs/platform-scaleway.md) `[x86_64]`
|
||||
- Baremetal:
|
||||
- [packet.net](docs/platform-packet.md) `[x86_64, arm64]`
|
||||
- [Raspberry Pi Model 3b](docs/platform-rpi3.md) `[arm64]`
|
||||
|
@ -3,14 +3,11 @@
|
||||
This is a quick guide to run LinuxKit on Scaleway (only VPS x86_64 for now)
|
||||
|
||||
## Setup
|
||||
Before you proceed it's recommanded that you set up the [Scaleway CLI](https://github.com/scaleway/scaleway-cli/)
|
||||
and perform an `scw login`. This will create a `$HOME/.scwrc` file containing the required API token.
|
||||
|
||||
You can also use the `SCW_TOKEN` environment variable to set a Scaleway token.
|
||||
The `-token` flag of the `linuxkit push scaleway` and `linuxkit run scaleway` can also be used.
|
||||
|
||||
The environment variable `SCW_TARGET_REGION` is used to set the region (there is also the `-region` flag)
|
||||
You must create a Scaleway Secret Key (available ine the [Scaleway Console](https://console.scaleway.com/account/credentials)) first.
|
||||
Then you can use it either with the `SCW_SECRET_KEY` environment variable or with the `-secret-key` flag of the `linuxkit push scaleway` and `linuxkit run scaleway` commands.
|
||||
|
||||
The environment variable `SCW_DEFAULT_ZONE` is used to set the zone (there is also the `-zone` flag)
|
||||
|
||||
## Build an image
|
||||
|
||||
@ -33,13 +30,13 @@ It can be overidden with the `-img-name` flag or the `SCW_IMAGE_NAME` environmen
|
||||
|
||||
**Note 1:** If an image (and snapshot) of the same name exists, it will be replaced.
|
||||
|
||||
**Note 2:** The image is region specific: if you create an image in `par1` you can't use is in `ams1`.
|
||||
**Note 2:** The image is zone specific: if you create an image in `par1` you can't use is in `ams1`.
|
||||
|
||||
### Push process
|
||||
|
||||
Building a Scaleway image have a special process. Basically:
|
||||
|
||||
* Create an `image-builder` instance with an additional volume, based on Ubuntu Xenial (only x86_64 for now)
|
||||
* Create an `image-builder` instance with an additional volume, based on Ubuntu Bionic (only x86_64 for now)
|
||||
* Copy the ISO image on this instance
|
||||
* Use `dd` to write the image on the additional volume (`/dev/vdb` by default)
|
||||
* Terminate the instance, create a snapshot, and create an image from the snapshot
|
||||
|
@ -20,11 +20,12 @@ func pushScaleway(args []string) {
|
||||
flags.PrintDefaults()
|
||||
}
|
||||
nameFlag := flags.String("img-name", "", "Overrides the name used to identify the image name in Scaleway's images. Defaults to the base of 'path' with the '.iso' suffix removed")
|
||||
tokenFlag := flags.String("token", "", "Token to connet to Scaleway API")
|
||||
secretKeyFlag := flags.String("secret-key", "", "Secret Key to connet to Scaleway API")
|
||||
sshKeyFlag := flags.String("ssh-key", os.Getenv("HOME")+"/.ssh/id_rsa", "SSH key file")
|
||||
instanceIDFlag := flags.String("instance-id", "", "Instance ID of a running Scaleway instance, with a second volume.")
|
||||
deviceNameFlag := flags.String("device-name", "/dev/vdb", "Device name on which the image will be copied")
|
||||
regionFlag := flags.String("region", defaultScalewayRegion, "Select scaleway region")
|
||||
zoneFlag := flags.String("zone", defaultScalewayZone, "Select Scaleway zone")
|
||||
projectIDFlag := flags.String("project-id", "", "Select Scaleway's project ID")
|
||||
noCleanFlag := flags.Bool("no-clean", false, "Do not remove temporary instance and volumes")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
@ -40,11 +41,12 @@ func pushScaleway(args []string) {
|
||||
path := remArgs[0]
|
||||
|
||||
name := getStringValue(scalewayNameVar, *nameFlag, "")
|
||||
token := getStringValue(tokenVar, *tokenFlag, "")
|
||||
secretKey := getStringValue(secretKeyVar, *secretKeyFlag, "")
|
||||
sshKeyFile := getStringValue(sshKeyVar, *sshKeyFlag, "")
|
||||
instanceID := getStringValue(instanceIDVar, *instanceIDFlag, "")
|
||||
deviceName := getStringValue(deviceNameVar, *deviceNameFlag, "")
|
||||
region := getStringValue(regionVar, *regionFlag, defaultScalewayRegion)
|
||||
zone := getStringValue(zoneVar, *zoneFlag, defaultScalewayZone)
|
||||
projectID := getStringValue(projectIDVar, *projectIDFlag, "")
|
||||
|
||||
const suffix = ".iso"
|
||||
if name == "" {
|
||||
@ -52,7 +54,7 @@ func pushScaleway(args []string) {
|
||||
name = filepath.Base(name)
|
||||
}
|
||||
|
||||
client, err := NewScalewayClient(token, region)
|
||||
client, err := NewScalewayClient(secretKey, zone, projectID)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to connect to Scaleway: %v", err)
|
||||
}
|
||||
|
@ -10,15 +10,16 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultScalewayInstanceType = "VC1S"
|
||||
defaultScalewayRegion = "par1"
|
||||
defaultScalewayInstanceType = "DEV1-S"
|
||||
defaultScalewayZone = "par1"
|
||||
|
||||
scalewayNameVar = "SCW_IMAGE_NAME" // non-standard
|
||||
tokenVar = "SCW_TOKEN" // non-standard
|
||||
secretKeyVar = "SCW_SECRET_KEY" // non-standard
|
||||
sshKeyVar = "SCW_SSH_KEY_FILE" // non-standard
|
||||
instanceIDVar = "SCW_INSTANCE_ID" // non-standard
|
||||
deviceNameVar = "SCW_DEVICE_NAME" // non-standard
|
||||
regionVar = "SCW_TARGET_REGION"
|
||||
scwZoneVar = "SCW_DEFAULT_ZONE"
|
||||
projectIDVar = "SCW_DEFAULT_PROJECT_ID"
|
||||
|
||||
instanceTypeVar = "SCW_RUN_TYPE" // non-standard
|
||||
)
|
||||
@ -35,8 +36,9 @@ func runScaleway(args []string) {
|
||||
}
|
||||
instanceTypeFlag := flags.String("instance-type", defaultScalewayInstanceType, "Scaleway instance type")
|
||||
instanceNameFlag := flags.String("instance-name", "linuxkit", "Name of the create instance, default to the image name")
|
||||
tokenFlag := flags.String("token", "", "Token to connect to Scaleway API")
|
||||
regionFlag := flags.String("region", defaultScalewayRegion, "Select Scaleway region")
|
||||
secretKeyFlag := flags.String("secret-key", "", "Secret Key to connect to Scaleway API")
|
||||
zoneFlag := flags.String("zone", defaultScalewayZone, "Select Scaleway zone")
|
||||
projectIDFlag := flags.String("project-id", "", "Select Scaleway's project ID")
|
||||
cleanFlag := flags.Bool("clean", false, "Remove instance")
|
||||
noAttachFlag := flags.Bool("no-attach", false, "Don't attach to serial port, you will have to connect to instance manually")
|
||||
|
||||
@ -54,10 +56,11 @@ func runScaleway(args []string) {
|
||||
|
||||
instanceType := getStringValue(instanceTypeVar, *instanceTypeFlag, defaultScalewayInstanceType)
|
||||
instanceName := getStringValue("", *instanceNameFlag, name)
|
||||
token := getStringValue(tokenVar, *tokenFlag, "")
|
||||
region := getStringValue(regionVar, *regionFlag, defaultScalewayRegion)
|
||||
secretKey := getStringValue(secretKeyVar, *secretKeyFlag, "")
|
||||
zone := getStringValue(scwZoneVar, *zoneFlag, defaultScalewayZone)
|
||||
projectID := getStringValue(projectIDVar, *projectIDFlag, "")
|
||||
|
||||
client, err := NewScalewayClient(token, region)
|
||||
client, err := NewScalewayClient(secretKey, zone, projectID)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to connect to Scaleway: %v", err)
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -11,143 +10,189 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/ScaleFT/sshkeys"
|
||||
gotty "github.com/moul/gotty-client"
|
||||
scw "github.com/scaleway/go-scaleway"
|
||||
"github.com/scaleway/go-scaleway/logger"
|
||||
"github.com/scaleway/go-scaleway/types"
|
||||
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
|
||||
"github.com/scaleway/scaleway-sdk-go/api/marketplace/v1"
|
||||
"github.com/scaleway/scaleway-sdk-go/scw"
|
||||
"github.com/scaleway/scaleway-sdk-go/scwconfig"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultScalewayCommercialType = "DEV1-S"
|
||||
defaultScalewayImageName = "Ubuntu Bionic"
|
||||
defaultScalewayImageArch = "x86_64"
|
||||
defaultVolumeSize = uint64(10000000000)
|
||||
)
|
||||
|
||||
// ScalewayClient contains state required for communication with Scaleway as well as the instance
|
||||
type ScalewayClient struct {
|
||||
api *scw.ScalewayAPI
|
||||
instanceAPI *instance.API
|
||||
marketplaceAPI *marketplace.API
|
||||
fileName string
|
||||
region string
|
||||
zone string
|
||||
sshConfig *ssh.ClientConfig
|
||||
}
|
||||
|
||||
// ScalewayConfig contains required field to read scaleway config file
|
||||
type ScalewayConfig struct {
|
||||
Organization string `json:"organization"`
|
||||
Token string `json:"token"`
|
||||
Version string `json:"version"`
|
||||
secretKey string
|
||||
}
|
||||
|
||||
// NewScalewayClient creates a new scaleway client
|
||||
func NewScalewayClient(token, region string) (*ScalewayClient, error) {
|
||||
func NewScalewayClient(secretKey, zone, projectID string) (*ScalewayClient, error) {
|
||||
var scwClient *scw.Client
|
||||
log.Debugf("Connecting to Scaleway")
|
||||
organization := ""
|
||||
if token == "" {
|
||||
log.Debugf("Using .scwrc file to get token")
|
||||
homeDir := os.Getenv("HOME")
|
||||
if homeDir == "" {
|
||||
homeDir = os.Getenv("USERPROFILE") // Windows support
|
||||
}
|
||||
if homeDir == "" {
|
||||
return nil, fmt.Errorf("Home directory not found")
|
||||
}
|
||||
swrcPath := filepath.Join(homeDir, ".scwrc")
|
||||
|
||||
file, err := ioutil.ReadFile(swrcPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error reading Scaleway config file: %v", err)
|
||||
}
|
||||
|
||||
var scalewayConfig ScalewayConfig
|
||||
err = json.Unmarshal(file, &scalewayConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error during unmarshal of Scaleway config file: %v", err)
|
||||
}
|
||||
|
||||
token = scalewayConfig.Token
|
||||
organization = scalewayConfig.Organization
|
||||
}
|
||||
|
||||
api, err := scw.NewScalewayAPI(organization, token, "", region)
|
||||
if secretKey == "" {
|
||||
config, err := scwconfig.Load()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l := logger.NewDisableLogger()
|
||||
api.Logger = l
|
||||
|
||||
if organization == "" {
|
||||
organisations, err := api.GetOrganization()
|
||||
scwClient, err = scw.NewClient(
|
||||
scw.WithConfig(config),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
api.Organization = organisations.Organizations[0].ID
|
||||
} else {
|
||||
scwZone, err := utils.ParseZone(zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scwClient, err = scw.NewClient(
|
||||
scw.WithAuth("", secretKey),
|
||||
scw.WithDefaultZone(scwZone),
|
||||
scw.WithDefaultProjectID(projectID),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
instanceAPI := instance.NewAPI(scwClient)
|
||||
marketplaceAPI := marketplace.NewAPI(scwClient)
|
||||
|
||||
client := &ScalewayClient{
|
||||
api: api,
|
||||
instanceAPI: instanceAPI,
|
||||
marketplaceAPI: marketplaceAPI,
|
||||
zone: zone,
|
||||
fileName: "",
|
||||
region: region,
|
||||
secretKey: secretKey,
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (s *ScalewayClient) getImageID(imageName, commercialType, arch string) (string, error) {
|
||||
imagesResp, err := s.marketplaceAPI.ListImages(&marketplace.ListImagesRequest{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, image := range imagesResp.Images {
|
||||
if image.Name == imageName {
|
||||
for _, version := range image.Versions {
|
||||
for _, localImage := range version.LocalImages {
|
||||
if localImage.Arch == arch {
|
||||
for _, compatibleCommercialType := range localImage.CompatibleCommercialTypes {
|
||||
if compatibleCommercialType == commercialType {
|
||||
return localImage.ID, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", errors.New("No image matching given requests")
|
||||
}
|
||||
|
||||
// CreateInstance create an instance with one additional volume
|
||||
func (s *ScalewayClient) CreateInstance() (string, error) {
|
||||
// get the Ubuntu Xenial image id
|
||||
image, err := s.api.GetImageID("Ubuntu Xenial", "x86_64") // TODO fix arch and use from args
|
||||
imageID, err := s.getImageID(defaultScalewayImageName, defaultScalewayCommercialType, defaultScalewayImageArch)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imageID := image.Identifier
|
||||
|
||||
var serverDefinition types.ScalewayServerDefinition
|
||||
|
||||
serverDefinition.Name = "linuxkit-builder"
|
||||
serverDefinition.Image = &imageID
|
||||
serverDefinition.CommercialType = "VC1M" // TODO use args?
|
||||
|
||||
// creation of second volume
|
||||
var volumeDefinition types.ScalewayVolumeDefinition
|
||||
volumeDefinition.Name = "linuxkit-builder-volume"
|
||||
volumeDefinition.Size = 50000000000 // FIX remove hardcoded value
|
||||
volumeDefinition.Type = "l_ssd"
|
||||
createVolumeRequest := &instance.CreateVolumeRequest{
|
||||
Name: "linuxkit-builder-volume",
|
||||
VolumeType: "l_ssd",
|
||||
Size: &defaultVolumeSize,
|
||||
}
|
||||
|
||||
log.Debugf("Creating volume on Scaleway")
|
||||
volumeID, err := s.api.PostVolume(volumeDefinition)
|
||||
volumeResp, err := s.instanceAPI.CreateVolume(createVolumeRequest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
serverDefinition.Volumes = make(map[string]string)
|
||||
serverDefinition.Volumes["1"] = volumeID
|
||||
volumeMap := make(map[string]*instance.VolumeTemplate)
|
||||
volumeTemplate := &instance.VolumeTemplate{
|
||||
Size: defaultVolumeSize,
|
||||
}
|
||||
volumeMap["0"] = volumeTemplate
|
||||
|
||||
serverID, err := s.api.PostServer(serverDefinition)
|
||||
createServerRequest := &instance.CreateServerRequest{
|
||||
Name: "linuxkit-builder",
|
||||
CommercialType: defaultScalewayCommercialType,
|
||||
DynamicIPRequired: true,
|
||||
Image: imageID,
|
||||
EnableIPv6: false,
|
||||
BootType: instance.ServerBootTypeLocal,
|
||||
Volumes: volumeMap,
|
||||
}
|
||||
|
||||
serverResp, err := s.instanceAPI.CreateServer(createServerRequest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Debugf("Created server %s on Scaleway", serverID)
|
||||
return serverID, nil
|
||||
attachVolumeRequest := &instance.AttachVolumeRequest{
|
||||
ServerID: serverResp.Server.ID,
|
||||
VolumeID: volumeResp.Volume.ID,
|
||||
}
|
||||
|
||||
_, err = s.instanceAPI.AttachVolume(attachVolumeRequest)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
log.Debugf("Created server %s on Scaleway", serverResp.Server.ID)
|
||||
return serverResp.Server.ID, nil
|
||||
}
|
||||
|
||||
// GetSecondVolumeID returns the ID of the second volume of the server
|
||||
func (s *ScalewayClient) GetSecondVolumeID(instanceID string) (string, error) {
|
||||
server, err := s.api.GetServer(instanceID)
|
||||
getServerRequest := &instance.GetServerRequest{
|
||||
ServerID: instanceID,
|
||||
}
|
||||
|
||||
serverResp, err := s.instanceAPI.GetServer(getServerRequest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
secondVolume, ok := server.Volumes["1"]
|
||||
secondVolume, ok := serverResp.Server.Volumes["1"]
|
||||
if !ok {
|
||||
return "", errors.New("No second volume found")
|
||||
}
|
||||
|
||||
return secondVolume.Identifier, nil
|
||||
return secondVolume.ID, nil
|
||||
}
|
||||
|
||||
// BootInstanceAndWait boots and wait for instance to be booted
|
||||
func (s *ScalewayClient) BootInstanceAndWait(instanceID string) error {
|
||||
err := s.api.PostServerAction(instanceID, "poweron")
|
||||
serverActionRequest := &instance.ServerActionRequest{
|
||||
ServerID: instanceID,
|
||||
Action: instance.ServerActionPoweron,
|
||||
}
|
||||
|
||||
_, err := s.instanceAPI.ServerAction(serverActionRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -156,14 +201,17 @@ func (s *ScalewayClient) BootInstanceAndWait(instanceID string) error {
|
||||
|
||||
// code taken from scaleway-cli, could need some changes
|
||||
promise := make(chan bool)
|
||||
var server *types.ScalewayServer
|
||||
var currentState string
|
||||
var server *instance.Server
|
||||
var currentState instance.ServerState
|
||||
|
||||
go func() {
|
||||
defer close(promise)
|
||||
|
||||
for {
|
||||
server, err = s.api.GetServer(instanceID)
|
||||
serverResp, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
|
||||
ServerID: instanceID,
|
||||
})
|
||||
server = serverResp.Server
|
||||
if err != nil {
|
||||
promise <- false
|
||||
return
|
||||
@ -173,20 +221,17 @@ func (s *ScalewayClient) BootInstanceAndWait(instanceID string) error {
|
||||
currentState = server.State
|
||||
}
|
||||
|
||||
if server.State == "running" {
|
||||
if server.State == instance.ServerStateRunning {
|
||||
break
|
||||
}
|
||||
if server.State == "stopped" {
|
||||
if server.State == instance.ServerStateStopped {
|
||||
promise <- false
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
ip := server.PublicAddress.IP
|
||||
if ip == "" && server.EnableIPV6 {
|
||||
ip = fmt.Sprintf("[%s]", server.IPV6.Address)
|
||||
}
|
||||
ip := server.PublicIP.Address.String()
|
||||
dest := fmt.Sprintf("%s:22", ip)
|
||||
for {
|
||||
conn, err := net.Dial("tcp", dest)
|
||||
@ -231,9 +276,18 @@ func getSSHAuth(sshKeyPath string) (ssh.Signer, error) {
|
||||
return nil, err
|
||||
}
|
||||
signer, err := ssh.ParsePrivateKey(buf)
|
||||
if err != nil {
|
||||
fmt.Print("Enter ssh key passphrase: ")
|
||||
bytePassword, err := terminal.ReadPassword(int(syscall.Stdin))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signer, err := sshkeys.ParseEncryptedPrivateKey(buf, bytePassword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return signer, nil
|
||||
}
|
||||
return signer, err
|
||||
}
|
||||
|
||||
@ -242,10 +296,13 @@ func (s *ScalewayClient) CopyImageToInstance(instanceID, path, sshKeyPath string
|
||||
_, base := filepath.Split(path)
|
||||
s.fileName = base
|
||||
|
||||
server, err := s.api.GetServer(instanceID)
|
||||
serverResp, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
|
||||
ServerID: instanceID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
server := serverResp.Server
|
||||
|
||||
signer, err := getSSHAuth(sshKeyPath)
|
||||
if err != nil {
|
||||
@ -260,7 +317,7 @@ func (s *ScalewayClient) CopyImageToInstance(instanceID, path, sshKeyPath string
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(), // TODO validate server before?
|
||||
}
|
||||
|
||||
client, err := ssh.Dial("tcp", server.PublicAddress.IP+":22", s.sshConfig) // TODO remove hardocoded port?
|
||||
client, err := ssh.Dial("tcp", server.PublicIP.Address.String()+":22", s.sshConfig) // TODO remove hardocoded port?
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -303,12 +360,16 @@ func (s *ScalewayClient) CopyImageToInstance(instanceID, path, sshKeyPath string
|
||||
|
||||
// WriteImageToVolume does a dd command on the remote instance via ssh
|
||||
func (s *ScalewayClient) WriteImageToVolume(instanceID, deviceName string) error {
|
||||
server, err := s.api.GetServer(instanceID)
|
||||
serverResp, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
|
||||
ServerID: instanceID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := ssh.Dial("tcp", server.PublicAddress.IP+":22", s.sshConfig) // TODO remove hardcoded port + use the same dial as before?
|
||||
server := serverResp.Server
|
||||
|
||||
client, err := ssh.Dial("tcp", server.PublicIP.Address.String()+":22", s.sshConfig) // TODO remove hardcoded port + use the same dial as before?
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -350,14 +411,12 @@ func (s *ScalewayClient) WriteImageToVolume(instanceID, deviceName string) error
|
||||
|
||||
// TerminateInstance terminates the instance and wait for termination
|
||||
func (s *ScalewayClient) TerminateInstance(instanceID string) error {
|
||||
server, err := s.api.GetServer(instanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("Shutting down server %s", instanceID)
|
||||
|
||||
err = s.api.PostServerAction(server.Identifier, "poweroff")
|
||||
_, err := s.instanceAPI.ServerAction(&instance.ServerActionRequest{
|
||||
ServerID: instanceID,
|
||||
Action: instance.ServerActionPoweroff,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -365,19 +424,24 @@ func (s *ScalewayClient) TerminateInstance(instanceID string) error {
|
||||
// code taken from scaleway-cli
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
var currentState string
|
||||
var currentState instance.ServerState
|
||||
|
||||
log.Debugf("Waiting for server to shutdown")
|
||||
|
||||
for {
|
||||
server, err = s.api.GetServer(instanceID)
|
||||
serverResp, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
|
||||
ServerID: instanceID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
server := serverResp.Server
|
||||
|
||||
if currentState != server.State {
|
||||
currentState = server.State
|
||||
}
|
||||
if server.State == "stopped" {
|
||||
if server.State == instance.ServerStateStopped {
|
||||
break
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
@ -387,51 +451,76 @@ func (s *ScalewayClient) TerminateInstance(instanceID string) error {
|
||||
|
||||
// CreateScalewayImage creates the image and delete old image and snapshot if same name
|
||||
func (s *ScalewayClient) CreateScalewayImage(instanceID, volumeID, name string) error {
|
||||
oldImage, err := s.api.GetImageID(name, "x86_64")
|
||||
oldImageID, err := s.getImageID(name, defaultScalewayCommercialType, defaultArch)
|
||||
if err == nil {
|
||||
err = s.api.DeleteImage(oldImage.Identifier)
|
||||
log.Debugf("deleting image %s", oldImageID)
|
||||
err = s.instanceAPI.DeleteImage(&instance.DeleteImageRequest{
|
||||
ImageID: oldImageID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
oldSnapshot, err := s.api.GetSnapshotID(name)
|
||||
oldSnapshotsResp, err := s.instanceAPI.ListSnapshots(&instance.ListSnapshotsRequest{
|
||||
Name: &name,
|
||||
}, scw.WithAllPages())
|
||||
if err == nil {
|
||||
err := s.api.DeleteSnapshot(oldSnapshot)
|
||||
for _, oldSnapshot := range oldSnapshotsResp.Snapshots {
|
||||
log.Debugf("deleting snapshot %s", oldSnapshot.ID)
|
||||
err = s.instanceAPI.DeleteSnapshot(&instance.DeleteSnapshotRequest{
|
||||
SnapshotID: oldSnapshot.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snapshotID, err := s.api.PostSnapshot(volumeID, name)
|
||||
log.Debugf("creating snapshot %s with volume %s", name, volumeID)
|
||||
snapshotResp, err := s.instanceAPI.CreateSnapshot(&instance.CreateSnapshotRequest{
|
||||
VolumeID: volumeID,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
imageID, err := s.api.PostImage(snapshotID, name, "", "x86_64") // TODO remove hardcoded arch
|
||||
log.Debugf("creating image %s with snapshot %s", name, snapshotResp.Snapshot.ID)
|
||||
imageResp, err := s.instanceAPI.CreateImage(&instance.CreateImageRequest{
|
||||
Name: name,
|
||||
Arch: instance.Arch(defaultArch),
|
||||
RootVolume: snapshotResp.Snapshot.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Image %s with ID %s created", name, imageID)
|
||||
log.Infof("Image %s with ID %s created", name, imageResp.Image.ID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteInstanceAndVolumes deletes the instance and the volumes attached
|
||||
func (s *ScalewayClient) DeleteInstanceAndVolumes(instanceID string) error {
|
||||
server, err := s.api.GetServer(instanceID)
|
||||
serverResp, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
|
||||
ServerID: instanceID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.api.DeleteServer(instanceID)
|
||||
err = s.instanceAPI.DeleteServer(&instance.DeleteServerRequest{
|
||||
ServerID: instanceID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, volume := range server.Volumes {
|
||||
err = s.api.DeleteVolume(volume.Identifier)
|
||||
for _, volume := range serverResp.Server.Volumes {
|
||||
err = s.instanceAPI.DeleteVolume(&instance.DeleteVolumeRequest{
|
||||
VolumeID: volume.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -445,33 +534,38 @@ func (s *ScalewayClient) DeleteInstanceAndVolumes(instanceID string) error {
|
||||
// CreateLinuxkitInstance creates an instance with the given linuxkit image
|
||||
func (s *ScalewayClient) CreateLinuxkitInstance(instanceName, imageName, instanceType string) (string, error) {
|
||||
// get the image ID
|
||||
image, err := s.api.GetImageID(imageName, "x86_64") // TODO fix arch and use from args
|
||||
imageResp, err := s.instanceAPI.ListImages(&instance.ListImagesRequest{
|
||||
Name: &imageName,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imageID := image.Identifier
|
||||
if len(imageResp.Images) != 1 {
|
||||
return "", fmt.Errorf("Image %s not found or found multiple times", imageName)
|
||||
}
|
||||
imageID := imageResp.Images[0].ID
|
||||
|
||||
var serverDefinition types.ScalewayServerDefinition
|
||||
|
||||
serverDefinition.Name = instanceName
|
||||
serverDefinition.Image = &imageID
|
||||
serverDefinition.CommercialType = instanceType
|
||||
serverDefinition.BootType = "local"
|
||||
|
||||
log.Debugf("Creating volume on Scaleway")
|
||||
|
||||
log.Debugf("Creating server %s on Scaleway", serverDefinition.Name)
|
||||
serverID, err := s.api.PostServer(serverDefinition)
|
||||
log.Debugf("Creating server %s on Scaleway", instanceName)
|
||||
serverResp, err := s.instanceAPI.CreateServer(&instance.CreateServerRequest{
|
||||
Name: instanceName,
|
||||
DynamicIPRequired: true,
|
||||
CommercialType: instanceType,
|
||||
Image: imageID,
|
||||
BootType: instance.ServerBootTypeLocal,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return serverID, nil
|
||||
return serverResp.Server.ID, nil
|
||||
}
|
||||
|
||||
// BootInstance boots the specified instance, and don't wait
|
||||
func (s *ScalewayClient) BootInstance(instanceID string) error {
|
||||
err := s.api.PostServerAction(instanceID, "poweron")
|
||||
_, err := s.instanceAPI.ServerAction(&instance.ServerActionRequest{
|
||||
ServerID: instanceID,
|
||||
Action: instance.ServerActionPoweron,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -481,7 +575,7 @@ func (s *ScalewayClient) BootInstance(instanceID string) error {
|
||||
// ConnectSerialPort connects to the serial port of the instance
|
||||
func (s *ScalewayClient) ConnectSerialPort(instanceID string) error {
|
||||
var gottyURL string
|
||||
switch s.region {
|
||||
switch s.zone {
|
||||
case "par1":
|
||||
gottyURL = "https://tty-par1.scaleway.com/v2/"
|
||||
case "ams1":
|
||||
@ -490,7 +584,7 @@ func (s *ScalewayClient) ConnectSerialPort(instanceID string) error {
|
||||
return errors.New("Instance have no region")
|
||||
}
|
||||
|
||||
fullURL := fmt.Sprintf("%s?arg=%s&arg=%s", gottyURL, s.api.Token, instanceID)
|
||||
fullURL := fmt.Sprintf("%s?arg=%s&arg=%s", gottyURL, s.secretKey, instanceID)
|
||||
|
||||
log.Debugf("Connection to %s", fullURL)
|
||||
gottyClient, err := gotty.NewClient(fullURL)
|
||||
|
@ -10,6 +10,7 @@ github.com/containerd/containerd v1.1.2
|
||||
github.com/containerd/continuity d8fb8589b0e8e85b8c8bbaa8840226d0dfeb7371
|
||||
github.com/creack/goselect 58854f77ee8d858ce751b0a9bcc5533fef7bfa9e
|
||||
github.com/davecgh/go-spew v1.1.0
|
||||
github.com/dchest/bcrypt_pbkdf 83f37f9c154a678179d11e218bff73ebe5717f99
|
||||
github.com/dgrijalva/jwt-go 6c8dedd55f8a2e41f605de6d5d66e51ed1f299fc
|
||||
github.com/docker/cli v18.06.0-ce
|
||||
github.com/docker/distribution 83389a148052d74ac602f5f1d62f86ff2f3c4aa5
|
||||
@ -54,7 +55,8 @@ github.com/radu-matei/azure-sdk-for-go 3b12823551999669c9a325a32472508e0af7978e
|
||||
github.com/radu-matei/azure-vhd-utils e52754d5569d2a643a7775f72ff2a6cf524f4c25
|
||||
github.com/renstrom/fuzzysearch 7a8f9a1c4bed53899ecd512daeaf8207cc454156
|
||||
github.com/rn/iso9660wrap baf8d62ad3155152b488d5ff9d4f2b9bb0d6986a
|
||||
github.com/scaleway/go-scaleway f8c3b31c65867b4cb96b3bd41e574c33fd1d69ae
|
||||
github.com/ScaleFT/sshkeys 82451a80368171b074c7129d43b47fc2773f6e9f
|
||||
github.com/scaleway/scaleway-sdk-go 20b731586975c078d9c2d7dd0002127e9e9cdef2
|
||||
github.com/sirupsen/logrus v1.0.3
|
||||
github.com/spf13/cobra v0.0.3
|
||||
github.com/spf13/pflag v1.0.1
|
||||
|
202
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/LICENSE
generated
vendored
Normal file
202
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
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.
|
10
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/NOTICE
generated
vendored
Normal file
10
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/NOTICE
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
sshkeys
|
||||
Copyright 2017 ScaleFT, Inc
|
||||
|
||||
This product includes software developed at ScaleFT, Inc.
|
||||
(https://www.scaleft.com/).
|
||||
|
||||
Portions of this software are derived from
|
||||
https://github.com/golang/crypto/blob/master/ssh/keys.go
|
||||
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
14
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/README.md
generated
vendored
Normal file
14
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/README.md
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
# sshkeys
|
||||
|
||||
[](https://godoc.org/github.com/ScaleFT/sshkeys)
|
||||
[](https://travis-ci.org/ScaleFT/sshkeys)
|
||||
|
||||
`sshkeys` provides utilities for parsing and marshalling cryptographic keys used for SSH, in both cleartext and encrypted formats.
|
||||
|
||||
[ssh.ParseRawPrivateKey](https://godoc.org/golang.org/x/crypto/ssh#ParseRawPrivateKey) only supports parsing a subset of the formats `sshkeys` supports, does not support parsing encrypted private keys, and does not support marshalling.
|
||||
|
||||
## Supported Formats
|
||||
|
||||
* OpenSSH's [PROTOCOL.key](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key) for RSA and ED25519 keys.
|
||||
* OpenSSH version >= 7.6 using aes256-ctr encryption
|
||||
* "Classic" PEM containing RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
|
275
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/marshal.go
generated
vendored
Normal file
275
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/marshal.go
generated
vendored
Normal file
@ -0,0 +1,275 @@
|
||||
package sshkeys
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
mrand "math/rand"
|
||||
|
||||
"github.com/dchest/bcrypt_pbkdf"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// Format of private key to use when Marshaling.
|
||||
type Format int
|
||||
|
||||
const (
|
||||
// FormatOpenSSHv1 encodes a private key using OpenSSH's PROTOCOL.key format: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
|
||||
FormatOpenSSHv1 Format = iota
|
||||
// FormatClassicPEM encodes private keys in PEM, with a key-specific encoding, as used by OpenSSH.
|
||||
FormatClassicPEM
|
||||
)
|
||||
|
||||
// MarshalOptions provides the Marshal function format and encryption options.
|
||||
type MarshalOptions struct {
|
||||
// Passphrase to encrypt private key with, if nil, the key will not be encrypted.
|
||||
Passphrase []byte
|
||||
// Format to encode the private key in.
|
||||
Format Format
|
||||
}
|
||||
|
||||
// Marshal converts a private key into an optionally encrypted format.
|
||||
func Marshal(pk interface{}, opts *MarshalOptions) ([]byte, error) {
|
||||
switch opts.Format {
|
||||
case FormatOpenSSHv1:
|
||||
return marshalOpenssh(pk, opts)
|
||||
case FormatClassicPEM:
|
||||
return marshalPem(pk, opts)
|
||||
default:
|
||||
return nil, fmt.Errorf("sshkeys: invalid format %d", opts.Format)
|
||||
}
|
||||
}
|
||||
|
||||
func marshalPem(pk interface{}, opts *MarshalOptions) ([]byte, error) {
|
||||
var err error
|
||||
var plain []byte
|
||||
var pemType string
|
||||
|
||||
switch key := pk.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
pemType = "RSA PRIVATE KEY"
|
||||
plain = x509.MarshalPKCS1PrivateKey(key)
|
||||
case *ecdsa.PrivateKey:
|
||||
pemType = "EC PRIVATE KEY"
|
||||
plain, err = x509.MarshalECPrivateKey(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *dsa.PrivateKey:
|
||||
pemType = "DSA PRIVATE KEY"
|
||||
plain, err = marshalDSAPrivateKey(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *ed25519.PrivateKey:
|
||||
return nil, fmt.Errorf("sshkeys: ed25519 keys must be marshaled with FormatOpenSSHv1")
|
||||
default:
|
||||
return nil, fmt.Errorf("sshkeys: unsupported key type %T", pk)
|
||||
}
|
||||
|
||||
if len(opts.Passphrase) > 0 {
|
||||
block, err := x509.EncryptPEMBlock(rand.Reader, pemType, plain, opts.Passphrase, x509.PEMCipherAES128)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pem.EncodeToMemory(block), nil
|
||||
}
|
||||
|
||||
return pem.EncodeToMemory(&pem.Block{
|
||||
Type: pemType,
|
||||
Bytes: plain,
|
||||
}), nil
|
||||
}
|
||||
|
||||
type dsaOpenssl struct {
|
||||
Version int
|
||||
P *big.Int
|
||||
Q *big.Int
|
||||
G *big.Int
|
||||
Pub *big.Int
|
||||
Priv *big.Int
|
||||
}
|
||||
|
||||
// https://github.com/golang/crypto/blob/master/ssh/keys.go#L793-L804
|
||||
func marshalDSAPrivateKey(pk *dsa.PrivateKey) ([]byte, error) {
|
||||
k := dsaOpenssl{
|
||||
Version: 0,
|
||||
P: pk.P,
|
||||
Q: pk.Q,
|
||||
G: pk.G,
|
||||
Pub: pk.Y,
|
||||
Priv: pk.X,
|
||||
}
|
||||
|
||||
return asn1.Marshal(k)
|
||||
}
|
||||
|
||||
const opensshv1Magic = "openssh-key-v1"
|
||||
|
||||
type opensshHeader struct {
|
||||
CipherName string
|
||||
KdfName string
|
||||
KdfOpts string
|
||||
NumKeys uint32
|
||||
PubKey string
|
||||
PrivKeyBlock string
|
||||
}
|
||||
|
||||
type opensshKey struct {
|
||||
Check1 uint32
|
||||
Check2 uint32
|
||||
Keytype string
|
||||
Rest []byte `ssh:"rest"`
|
||||
}
|
||||
|
||||
type opensshRsa struct {
|
||||
N *big.Int
|
||||
E *big.Int
|
||||
D *big.Int
|
||||
Iqmp *big.Int
|
||||
P *big.Int
|
||||
Q *big.Int
|
||||
Comment string
|
||||
Pad []byte `ssh:"rest"`
|
||||
}
|
||||
|
||||
type opensshED25519 struct {
|
||||
Pub []byte
|
||||
Priv []byte
|
||||
Comment string
|
||||
Pad []byte `ssh:"rest"`
|
||||
}
|
||||
|
||||
func padBytes(data []byte, blocksize int) []byte {
|
||||
if blocksize != 0 {
|
||||
var i byte
|
||||
for i = byte(1); len(data)%blocksize != 0; i++ {
|
||||
data = append(data, i&0xFF)
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func marshalOpenssh(pk interface{}, opts *MarshalOptions) ([]byte, error) {
|
||||
var blocksize int
|
||||
var keylen int
|
||||
|
||||
out := opensshHeader{
|
||||
CipherName: "none",
|
||||
KdfName: "none",
|
||||
KdfOpts: "",
|
||||
NumKeys: 1,
|
||||
PubKey: "",
|
||||
}
|
||||
|
||||
if len(opts.Passphrase) > 0 {
|
||||
out.CipherName = "aes256-cbc"
|
||||
out.KdfName = "bcrypt"
|
||||
keylen = keySizeAES256
|
||||
blocksize = aes.BlockSize
|
||||
}
|
||||
|
||||
check := mrand.Uint32()
|
||||
pk1 := opensshKey{
|
||||
Check1: check,
|
||||
Check2: check,
|
||||
}
|
||||
|
||||
switch key := pk.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
k := &opensshRsa{
|
||||
N: key.N,
|
||||
E: big.NewInt(int64(key.E)),
|
||||
D: key.D,
|
||||
Iqmp: key.Precomputed.Qinv,
|
||||
P: key.Primes[0],
|
||||
Q: key.Primes[1],
|
||||
Comment: "",
|
||||
}
|
||||
|
||||
data := ssh.Marshal(k)
|
||||
pk1.Keytype = ssh.KeyAlgoRSA
|
||||
pk1.Rest = data
|
||||
publicKey, err := ssh.NewPublicKey(&key.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out.PubKey = string(publicKey.Marshal())
|
||||
|
||||
case ed25519.PrivateKey:
|
||||
k := opensshED25519{
|
||||
Pub: key.Public().(ed25519.PublicKey),
|
||||
Priv: key,
|
||||
}
|
||||
data := ssh.Marshal(k)
|
||||
pk1.Keytype = ssh.KeyAlgoED25519
|
||||
pk1.Rest = data
|
||||
|
||||
publicKey, err := ssh.NewPublicKey(key.Public())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out.PubKey = string(publicKey.Marshal())
|
||||
default:
|
||||
return nil, fmt.Errorf("sshkeys: unsupported key type %T", pk)
|
||||
}
|
||||
|
||||
if len(opts.Passphrase) > 0 {
|
||||
rounds := 16
|
||||
ivlen := blocksize
|
||||
salt := make([]byte, blocksize)
|
||||
_, err := rand.Read(salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
kdfdata, err := bcrypt_pbkdf.Key(opts.Passphrase, salt, rounds, keylen+ivlen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iv := kdfdata[keylen : ivlen+keylen]
|
||||
aeskey := kdfdata[0:keylen]
|
||||
|
||||
block, err := aes.NewCipher(aeskey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pkblock := padBytes(ssh.Marshal(pk1), blocksize)
|
||||
|
||||
cbc := cipher.NewCBCEncrypter(block, iv)
|
||||
cbc.CryptBlocks(pkblock, pkblock)
|
||||
|
||||
out.PrivKeyBlock = string(pkblock)
|
||||
|
||||
var opts struct {
|
||||
Salt []byte
|
||||
Rounds uint32
|
||||
}
|
||||
|
||||
opts.Salt = salt
|
||||
opts.Rounds = uint32(rounds)
|
||||
|
||||
out.KdfOpts = string(ssh.Marshal(&opts))
|
||||
} else {
|
||||
out.PrivKeyBlock = string(ssh.Marshal(pk1))
|
||||
}
|
||||
|
||||
outBytes := []byte(opensshv1Magic)
|
||||
outBytes = append(outBytes, 0)
|
||||
outBytes = append(outBytes, ssh.Marshal(out)...)
|
||||
block := &pem.Block{
|
||||
Type: "OPENSSH PRIVATE KEY",
|
||||
Bytes: outBytes,
|
||||
}
|
||||
return pem.EncodeToMemory(block), nil
|
||||
}
|
244
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/parse.go
generated
vendored
Normal file
244
src/cmd/linuxkit/vendor/github.com/ScaleFT/sshkeys/parse.go
generated
vendored
Normal file
@ -0,0 +1,244 @@
|
||||
// Portions of this file are based on https://github.com/golang/crypto/blob/master/ssh/keys.go
|
||||
//
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package sshkeys
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/dchest/bcrypt_pbkdf"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// ErrIncorrectPassword is returned when the supplied passphrase was not correct for an encrypted private key.
|
||||
var ErrIncorrectPassword = errors.New("sshkeys: Invalid Passphrase")
|
||||
|
||||
const keySizeAES256 = 32
|
||||
|
||||
// ParseEncryptedPrivateKey returns a Signer from an encrypted private key. It supports
|
||||
// the same keys as ParseEncryptedRawPrivateKey.
|
||||
func ParseEncryptedPrivateKey(data []byte, passphrase []byte) (ssh.Signer, error) {
|
||||
key, err := ParseEncryptedRawPrivateKey(data, passphrase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ssh.NewSignerFromKey(key)
|
||||
}
|
||||
|
||||
// ParseEncryptedRawPrivateKey returns a private key from an encrypted private key. It
|
||||
// supports RSA (PKCS#1 or OpenSSH), DSA (OpenSSL), and ECDSA private keys.
|
||||
//
|
||||
// ErrIncorrectPassword will be returned if the supplied passphrase is wrong,
|
||||
// but some formats like RSA in PKCS#1 detecting a wrong passphrase is difficult,
|
||||
// and other parse errors may be returned.
|
||||
func ParseEncryptedRawPrivateKey(data []byte, passphrase []byte) (interface{}, error) {
|
||||
var err error
|
||||
|
||||
block, _ := pem.Decode(data)
|
||||
if block == nil {
|
||||
return nil, errors.New("no PEM block found")
|
||||
}
|
||||
|
||||
if x509.IsEncryptedPEMBlock(block) {
|
||||
data, err = x509.DecryptPEMBlock(block, passphrase)
|
||||
if err == x509.IncorrectPasswordError {
|
||||
return nil, ErrIncorrectPassword
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
data = block.Bytes
|
||||
}
|
||||
|
||||
switch block.Type {
|
||||
case "RSA PRIVATE KEY":
|
||||
pk, err := x509.ParsePKCS1PrivateKey(data)
|
||||
if err != nil {
|
||||
// The Algos for PEM Encryption do not include strong message authentication,
|
||||
// so sometimes DecryptPEMBlock works, but ParsePKCS1PrivateKey fails with an asn1 error.
|
||||
// We are just catching the most common prefix here...
|
||||
if strings.HasPrefix(err.Error(), "asn1: structure error") {
|
||||
return nil, ErrIncorrectPassword
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return pk, nil
|
||||
case "EC PRIVATE KEY":
|
||||
return x509.ParseECPrivateKey(data)
|
||||
case "DSA PRIVATE KEY":
|
||||
return ssh.ParseDSAPrivateKey(data)
|
||||
case "OPENSSH PRIVATE KEY":
|
||||
return parseOpenSSHPrivateKey(data, passphrase)
|
||||
default:
|
||||
return nil, fmt.Errorf("sshkeys: unsupported key type %q", block.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func parseOpenSSHPrivateKey(data []byte, passphrase []byte) (interface{}, error) {
|
||||
magic := append([]byte(opensshv1Magic), 0)
|
||||
if !bytes.Equal(magic, data[0:len(magic)]) {
|
||||
return nil, errors.New("sshkeys: invalid openssh private key format")
|
||||
}
|
||||
remaining := data[len(magic):]
|
||||
|
||||
w := opensshHeader{}
|
||||
|
||||
if err := ssh.Unmarshal(remaining, &w); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if w.NumKeys != 1 {
|
||||
return nil, fmt.Errorf("sshkeys: NumKeys must be 1: %d", w.NumKeys)
|
||||
}
|
||||
|
||||
var privateKeyBytes []byte
|
||||
var encrypted bool
|
||||
|
||||
switch {
|
||||
// OpenSSH supports bcrypt KDF w/ AES256-CBC or AES256-CTR mode
|
||||
case w.KdfName == "bcrypt" && w.CipherName == "aes256-cbc":
|
||||
iv, block, err := extractBcryptIvBlock(passphrase, w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cbc := cipher.NewCBCDecrypter(block, iv)
|
||||
privateKeyBytes = []byte(w.PrivKeyBlock)
|
||||
cbc.CryptBlocks(privateKeyBytes, privateKeyBytes)
|
||||
|
||||
encrypted = true
|
||||
|
||||
case w.KdfName == "bcrypt" && w.CipherName == "aes256-ctr":
|
||||
iv, block, err := extractBcryptIvBlock(passphrase, w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
privateKeyBytes = []byte(w.PrivKeyBlock)
|
||||
stream.XORKeyStream(privateKeyBytes, privateKeyBytes)
|
||||
|
||||
encrypted = true
|
||||
|
||||
case w.KdfName == "none" && w.CipherName == "none":
|
||||
privateKeyBytes = []byte(w.PrivKeyBlock)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("sshkeys: unknown Cipher/KDF: %s:%s", w.CipherName, w.KdfName)
|
||||
}
|
||||
|
||||
pk1 := opensshKey{}
|
||||
|
||||
if err := ssh.Unmarshal(privateKeyBytes, &pk1); err != nil {
|
||||
if encrypted {
|
||||
return nil, ErrIncorrectPassword
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pk1.Check1 != pk1.Check2 {
|
||||
return nil, ErrIncorrectPassword
|
||||
}
|
||||
|
||||
// we only handle ed25519 and rsa keys currently
|
||||
switch pk1.Keytype {
|
||||
case ssh.KeyAlgoRSA:
|
||||
// https://github.com/openssh/openssh-portable/blob/V_7_4_P1/sshkey.c#L2760-L2773
|
||||
key := opensshRsa{}
|
||||
|
||||
err := ssh.Unmarshal(pk1.Rest, &key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, b := range key.Pad {
|
||||
if int(b) != i+1 {
|
||||
return nil, errors.New("sshkeys: padding not as expected")
|
||||
}
|
||||
}
|
||||
|
||||
pk := &rsa.PrivateKey{
|
||||
PublicKey: rsa.PublicKey{
|
||||
N: key.N,
|
||||
E: int(key.E.Int64()),
|
||||
},
|
||||
D: key.D,
|
||||
Primes: []*big.Int{key.P, key.Q},
|
||||
}
|
||||
|
||||
err = pk.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pk.Precompute()
|
||||
|
||||
return pk, nil
|
||||
case ssh.KeyAlgoED25519:
|
||||
key := opensshED25519{}
|
||||
|
||||
err := ssh.Unmarshal(pk1.Rest, &key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(key.Priv) != ed25519.PrivateKeySize {
|
||||
return nil, errors.New("sshkeys: private key unexpected length")
|
||||
}
|
||||
|
||||
for i, b := range key.Pad {
|
||||
if int(b) != i+1 {
|
||||
return nil, errors.New("sshkeys: padding not as expected")
|
||||
}
|
||||
}
|
||||
|
||||
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
|
||||
copy(pk, key.Priv)
|
||||
return pk, nil
|
||||
default:
|
||||
return nil, errors.New("sshkeys: unhandled key type")
|
||||
}
|
||||
}
|
||||
|
||||
func extractBcryptIvBlock(passphrase []byte, w opensshHeader) ([]byte, cipher.Block, error) {
|
||||
cipherKeylen := keySizeAES256
|
||||
cipherIvLen := aes.BlockSize
|
||||
|
||||
var opts struct {
|
||||
Salt []byte
|
||||
Rounds uint32
|
||||
}
|
||||
|
||||
if err := ssh.Unmarshal([]byte(w.KdfOpts), &opts); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
kdfdata, err := bcrypt_pbkdf.Key(passphrase, opts.Salt, int(opts.Rounds), cipherKeylen+cipherIvLen)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
iv := kdfdata[cipherKeylen : cipherIvLen+cipherKeylen]
|
||||
aeskey := kdfdata[0:cipherKeylen]
|
||||
block, err := aes.NewCipher(aeskey)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return iv, block, nil
|
||||
}
|
27
src/cmd/linuxkit/vendor/github.com/dchest/bcrypt_pbkdf/LICENSE
generated
vendored
Normal file
27
src/cmd/linuxkit/vendor/github.com/dchest/bcrypt_pbkdf/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2014 Dmitry Chestnykh <dmitry@codingrobots.com>
|
||||
Copyright (c) 2010 The Go Authors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
21
src/cmd/linuxkit/vendor/github.com/dchest/bcrypt_pbkdf/README
generated
vendored
Normal file
21
src/cmd/linuxkit/vendor/github.com/dchest/bcrypt_pbkdf/README
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
Go implementation of bcrypt_pbkdf(3) from OpenBSD
|
||||
(a variant of PBKDF2 with bcrypt-based PRF).
|
||||
|
||||
|
||||
USAGE
|
||||
|
||||
func Key(password, salt []byte, rounds, keyLen int) ([]byte, error)
|
||||
|
||||
|
||||
Key derives a key from the password, salt and rounds count, returning a
|
||||
[]byte of length keyLen that can be used as cryptographic key.
|
||||
|
||||
Remember to get a good random salt of at least 16 bytes. Using a higher
|
||||
rounds count will increase the cost of an exhaustive search but will also
|
||||
make derivation proportionally slower.
|
||||
|
||||
|
||||
REFERENCES
|
||||
|
||||
* http://www.tedunangst.com/flak/post/bcrypt-pbkdf
|
||||
* http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c
|
97
src/cmd/linuxkit/vendor/github.com/dchest/bcrypt_pbkdf/bcrypt_pbkdf.go
generated
vendored
Normal file
97
src/cmd/linuxkit/vendor/github.com/dchest/bcrypt_pbkdf/bcrypt_pbkdf.go
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright 2014 Dmitry Chestnykh. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package bcrypt_pbkdf implements password-based key derivation function based
|
||||
// on bcrypt compatible with bcrypt_pbkdf(3) from OpenBSD.
|
||||
package bcrypt_pbkdf
|
||||
|
||||
import (
|
||||
"crypto/sha512"
|
||||
"errors"
|
||||
|
||||
// NOTE! Requires blowfish package version from Aug 1, 2014 or later.
|
||||
// Will produce incorrect results if the package is older.
|
||||
// See commit message for details: http://goo.gl/wx6g8O
|
||||
"golang.org/x/crypto/blowfish"
|
||||
)
|
||||
|
||||
// Key derives a key from the password, salt and rounds count, returning a
|
||||
// []byte of length keyLen that can be used as cryptographic key.
|
||||
//
|
||||
// Remember to get a good random salt of at least 16 bytes. Using a higher
|
||||
// rounds count will increase the cost of an exhaustive search but will also
|
||||
// make derivation proportionally slower.
|
||||
func Key(password, salt []byte, rounds, keyLen int) ([]byte, error) {
|
||||
if rounds < 1 {
|
||||
return nil, errors.New("bcrypt_pbkdf: number of rounds is too small")
|
||||
}
|
||||
if len(password) == 0 {
|
||||
return nil, errors.New("bcrypt_pbkdf: empty password")
|
||||
}
|
||||
if len(salt) == 0 || len(salt) > 1<<20 {
|
||||
return nil, errors.New("bcrypt_pbkdf: bad salt length")
|
||||
}
|
||||
if keyLen > 1024 {
|
||||
return nil, errors.New("bcrypt_pbkdf: keyLen is too large")
|
||||
}
|
||||
var shapass, shasalt [sha512.Size]byte
|
||||
var out, tmp [32]byte
|
||||
var cnt [4]byte
|
||||
|
||||
numBlocks := (keyLen + len(out) - 1) / len(out)
|
||||
key := make([]byte, numBlocks*len(out))
|
||||
|
||||
h := sha512.New()
|
||||
h.Write(password)
|
||||
h.Sum(shapass[:0])
|
||||
|
||||
for block := 1; block <= numBlocks; block++ {
|
||||
h.Reset()
|
||||
h.Write(salt)
|
||||
cnt[0] = byte(block >> 24)
|
||||
cnt[1] = byte(block >> 16)
|
||||
cnt[2] = byte(block >> 8)
|
||||
cnt[3] = byte(block)
|
||||
h.Write(cnt[:])
|
||||
bcryptHash(tmp[:], shapass[:], h.Sum(shasalt[:0]))
|
||||
copy(out[:], tmp[:])
|
||||
|
||||
for i := 2; i <= rounds; i++ {
|
||||
h.Reset()
|
||||
h.Write(tmp[:])
|
||||
bcryptHash(tmp[:], shapass[:], h.Sum(shasalt[:0]))
|
||||
for j := 0; j < len(out); j++ {
|
||||
out[j] ^= tmp[j]
|
||||
}
|
||||
}
|
||||
|
||||
for i, v := range out {
|
||||
key[i*numBlocks+(block-1)] = v
|
||||
}
|
||||
}
|
||||
return key[:keyLen], nil
|
||||
}
|
||||
|
||||
var magic = []byte("OxychromaticBlowfishSwatDynamite")
|
||||
|
||||
func bcryptHash(out, shapass, shasalt []byte) {
|
||||
c, err := blowfish.NewSaltedCipher(shapass, shasalt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i := 0; i < 64; i++ {
|
||||
blowfish.ExpandKey(shasalt, c)
|
||||
blowfish.ExpandKey(shapass, c)
|
||||
}
|
||||
copy(out[:], magic)
|
||||
for i := 0; i < 32; i += 8 {
|
||||
for j := 0; j < 64; j++ {
|
||||
c.Encrypt(out[i:i+8], out[i:i+8])
|
||||
}
|
||||
}
|
||||
// Swap bytes due to different endianness.
|
||||
for i := 0; i < 32; i += 4 {
|
||||
out[i+3], out[i+2], out[i+1], out[i] = out[i], out[i+1], out[i+2], out[i+3]
|
||||
}
|
||||
}
|
22
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/LICENSE
generated
vendored
22
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/LICENSE
generated
vendored
@ -1,22 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Manfred Touron
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
171
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/README.md
generated
vendored
171
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/README.md
generated
vendored
@ -1,171 +0,0 @@
|
||||
# AnonUUID
|
||||
|
||||
[](https://travis-ci.org/moul/anonuuid)
|
||||
[](https://godoc.org/github.com/moul/anonuuid)
|
||||
[](https://coveralls.io/github/moul/anonuuid?branch=master)
|
||||
|
||||
:wrench: Anonymize UUIDs outputs (written in Golang)
|
||||
|
||||

|
||||
|
||||
**anonuuid** anonymize an input string by replacing all UUIDs by an anonymized
|
||||
new one.
|
||||
|
||||
The fake UUIDs are cached, so if AnonUUID encounter the same real UUIDs multiple
|
||||
times, the translation will be the same.
|
||||
|
||||
## Usage
|
||||
|
||||
```console
|
||||
$ anonuuid --help
|
||||
NAME:
|
||||
anonuuid - Anonymize UUIDs outputs
|
||||
|
||||
USAGE:
|
||||
anonuuid [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.0.0-dev
|
||||
|
||||
AUTHOR(S):
|
||||
Manfred Touron <https://github.com/moul>
|
||||
|
||||
COMMANDS:
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--hexspeak Generate hexspeak style fake UUIDs
|
||||
--random, -r Generate random fake UUIDs
|
||||
--keep-beginning Keep first part of the UUID unchanged
|
||||
--keep-end Keep last part of the UUID unchanged
|
||||
--prefix, -p Prefix generated UUIDs
|
||||
--suffix Suffix generated UUIDs
|
||||
--help, -h show help
|
||||
--version, -v print the version
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Replace all UUIDs and cache the correspondance.
|
||||
|
||||
```command
|
||||
$ anonuuid git:(master) ✗ cat <<EOF | anonuuid
|
||||
VOLUMES_0_SERVER_ID=15573749-c89d-41dd-a655-16e79bed52e0
|
||||
VOLUMES_0_SERVER_NAME=hello
|
||||
VOLUMES_0_ID=c245c3cb-3336-4567-ada1-70cb1fe4eefe
|
||||
VOLUMES_0_SIZE=50000000000
|
||||
ORGANIZATION=fe1e54e8-d69d-4f7c-a9f1-42069e03da31
|
||||
TEST=15573749-c89d-41dd-a655-16e79bed52e0
|
||||
EOF
|
||||
VOLUMES_0_SERVER_ID=00000000-0000-0000-0000-000000000000
|
||||
VOLUMES_0_SERVER_NAME=hello
|
||||
VOLUMES_0_ID=11111111-1111-1111-1111-111111111111
|
||||
VOLUMES_0_SIZE=50000000000
|
||||
ORGANIZATION=22222222-2222-2222-2222-222222222222
|
||||
TEST=00000000-0000-0000-0000-000000000000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Inline
|
||||
|
||||
```command
|
||||
$ echo 'VOLUMES_0_SERVER_ID=15573749-c89d-41dd-a655-16e79bed52e0 VOLUMES_0_SERVER_NAME=bitrig1 VOLUMES_0_ID=c245c3cb-3336-4567-ada1-70cb1fe4eefe VOLUMES_0_SIZE=50000000000 ORGANIZATION=fe1e54e8-d69d-4f7c-a9f1-42069e03da31 TEST=15573749-c89d-41dd-a655-16e79bed52e0' | ./anonuuid
|
||||
VOLUMES_0_SERVER_ID=00000000-0000-0000-0000-000000000000 VOLUMES_0_SERVER_NAME=bitrig1 VOLUMES_0_ID=11111111-1111-1111-1111-111111111111 VOLUMES_0_SIZE=50000000000 ORGANIZATION=22222222-2222-2222-2222-222222222222 TEST=00000000-0000-0000-0000-000000000000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```command
|
||||
$ curl -s https://api.pathwar.net/achievements\?max_results\=2 | anonuuid | jq .
|
||||
{
|
||||
"_items": [
|
||||
{
|
||||
"_updated": "Thu, 30 Apr 2015 13:00:58 GMT",
|
||||
"description": "You",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "achievements/00000000-0000-0000-0000-000000000000",
|
||||
"title": "achievement"
|
||||
}
|
||||
},
|
||||
"_created": "Thu, 30 Apr 2015 13:00:58 GMT",
|
||||
"_id": "00000000-0000-0000-0000-000000000000",
|
||||
"_etag": "b1e9f850accfcb952c58384db41d89728890a69f",
|
||||
"name": "finish-20-levels"
|
||||
},
|
||||
{
|
||||
"_updated": "Thu, 30 Apr 2015 13:01:07 GMT",
|
||||
"description": "You",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "achievements/11111111-1111-1111-1111-111111111111",
|
||||
"title": "achievement"
|
||||
}
|
||||
},
|
||||
"_created": "Thu, 30 Apr 2015 13:01:07 GMT",
|
||||
"_id": "11111111-1111-1111-1111-111111111111",
|
||||
"_etag": "c346f5e1c4f7658f2dfc4124efa87aba909a9821",
|
||||
"name": "buy-30-levels"
|
||||
}
|
||||
],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "achievements?max_results=2",
|
||||
"title": "achievements"
|
||||
},
|
||||
"last": {
|
||||
"href": "achievements?max_results=2&page=23",
|
||||
"title": "last page"
|
||||
},
|
||||
"parent": {
|
||||
"href": "/",
|
||||
"title": "home"
|
||||
},
|
||||
"next": {
|
||||
"href": "achievements?max_results=2&page=2",
|
||||
"title": "next page"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"max_results": 2,
|
||||
"total": 46,
|
||||
"page": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
Using go
|
||||
|
||||
- `go get github.com/moul/anonuuid/...`
|
||||
|
||||
## Changelog
|
||||
|
||||
### [v1.1.0](https://github.com/moul/anonuuid/releases/tag/v1.1.0) (2018-04-02)
|
||||
|
||||
* Switch from `Godep` to `Glide`
|
||||
* Add mutex to protect the cache field ([@QuentinPerez](https://github.com/QuentinPerez))
|
||||
* Switch from `Party` to `Godep`
|
||||
* Support of `--suffix=xxx`, `--keep-beginning` and `--keep-end` options ([#4](https://github.com/moul/anonuuid/issues/4))
|
||||
* Using **party** to stabilize vendor package versions ([#8](https://github.com/moul/anonuuid/issues/8))
|
||||
* Add homebrew package ([#6](https://github.com/moul/anonuuid/issues/6))
|
||||
|
||||
[full commits list](https://github.com/moul/anonuuid/compare/v1.0.0...master)
|
||||
|
||||
### [v1.0.0](https://github.com/moul/anonuuid/releases/tag/v1.0.0) (2015-10-07)
|
||||
|
||||
**Initial release**
|
||||
|
||||
#### Features
|
||||
|
||||
* Support of `--hexspeak` option
|
||||
* Support of `--random` option
|
||||
* Support of `--prefix` option
|
||||
* Anonymize input stream
|
||||
* Anonymize files
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
229
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/anonuuid.go
generated
vendored
229
src/cmd/linuxkit/vendor/github.com/moul/anonuuid/anonuuid.go
generated
vendored
@ -1,229 +0,0 @@
|
||||
package anonuuid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// UUIDRegex is the regex used to find UUIDs in texts
|
||||
UUIDRegex = "[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}"
|
||||
)
|
||||
|
||||
// AnonUUID is the main structure, it contains the cache map and helpers
|
||||
type AnonUUID struct {
|
||||
cache map[string]string
|
||||
|
||||
guard sync.Mutex // cache guard
|
||||
|
||||
// Hexspeak flag will generate hexspeak style fake UUIDs
|
||||
Hexspeak bool
|
||||
|
||||
// Random flag will generate random fake UUIDs
|
||||
Random bool
|
||||
|
||||
// Prefix will be the beginning of all the generated UUIDs
|
||||
Prefix string
|
||||
|
||||
// Suffix will be the end of all the generated UUIDs
|
||||
Suffix string
|
||||
|
||||
// AllowNonUUIDInput tells FakeUUID to accept non UUID input string
|
||||
AllowNonUUIDInput bool
|
||||
|
||||
// KeepBeginning tells FakeUUID to let the beginning of the UUID as it is
|
||||
KeepBeginning bool
|
||||
|
||||
// KeepEnd tells FakeUUID to let the last part of the UUID as it is
|
||||
KeepEnd bool
|
||||
}
|
||||
|
||||
// Sanitize takes a string as input and return sanitized string
|
||||
func (a *AnonUUID) Sanitize(input string) string {
|
||||
r := regexp.MustCompile(UUIDRegex)
|
||||
|
||||
return r.ReplaceAllStringFunc(input, func(m string) string {
|
||||
parts := r.FindStringSubmatch(m)
|
||||
return a.FakeUUID(parts[0])
|
||||
})
|
||||
}
|
||||
|
||||
// FakeUUID takes a word (real UUID or standard string) and returns its corresponding (mapped) fakeUUID
|
||||
func (a *AnonUUID) FakeUUID(input string) string {
|
||||
if !a.AllowNonUUIDInput {
|
||||
err := IsUUID(input)
|
||||
if err != nil {
|
||||
return "invaliduuid"
|
||||
}
|
||||
}
|
||||
a.guard.Lock()
|
||||
defer a.guard.Unlock()
|
||||
if _, ok := a.cache[input]; !ok {
|
||||
|
||||
if a.KeepBeginning {
|
||||
a.Prefix = input[:8]
|
||||
}
|
||||
|
||||
if a.KeepEnd {
|
||||
a.Suffix = input[36-12:]
|
||||
}
|
||||
|
||||
if a.Prefix != "" {
|
||||
matched, err := regexp.MatchString("^[a-z0-9]+$", a.Prefix)
|
||||
if err != nil || !matched {
|
||||
a.Prefix = "invalidprefix"
|
||||
}
|
||||
}
|
||||
|
||||
if a.Suffix != "" {
|
||||
matched, err := regexp.MatchString("^[a-z0-9]+$", a.Suffix)
|
||||
if err != nil || !matched {
|
||||
a.Suffix = "invalsuffix"
|
||||
}
|
||||
}
|
||||
|
||||
var fakeUUID string
|
||||
var err error
|
||||
if a.Hexspeak {
|
||||
fakeUUID, err = GenerateHexspeakUUID(len(a.cache))
|
||||
} else if a.Random {
|
||||
fakeUUID, err = GenerateRandomUUID(10)
|
||||
} else {
|
||||
fakeUUID, err = GenerateLenUUID(len(a.cache))
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate an UUID: %v", err)
|
||||
}
|
||||
|
||||
if a.Prefix != "" {
|
||||
fakeUUID, err = PrefixUUID(a.Prefix, fakeUUID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if a.Suffix != "" {
|
||||
fakeUUID, err = SuffixUUID(a.Suffix, fakeUUID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: check for duplicates and retry
|
||||
|
||||
a.cache[input] = fakeUUID
|
||||
}
|
||||
return a.cache[input]
|
||||
}
|
||||
|
||||
// New returns a prepared AnonUUID structure
|
||||
func New() *AnonUUID {
|
||||
return &AnonUUID{
|
||||
cache: make(map[string]string),
|
||||
Hexspeak: false,
|
||||
Random: false,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
}
|
||||
|
||||
// PrefixUUID returns a prefixed UUID
|
||||
func PrefixUUID(prefix string, uuid string) (string, error) {
|
||||
uuidLetters := uuid[:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
|
||||
prefixedUUID, err := FormatUUID(prefix + uuidLetters)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return prefixedUUID, nil
|
||||
}
|
||||
|
||||
// SuffixUUID returns a suffixed UUID
|
||||
func SuffixUUID(suffix string, uuid string) (string, error) {
|
||||
uuidLetters := uuid[:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
|
||||
uuidLetters = uuidLetters[:32-len(suffix)] + suffix
|
||||
suffixedUUID, err := FormatUUID(uuidLetters)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return suffixedUUID, nil
|
||||
}
|
||||
|
||||
// IsUUID returns nil if the input is an UUID, else it returns an error
|
||||
func IsUUID(input string) error {
|
||||
matched, err := regexp.MatchString("^"+UUIDRegex+"$", input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !matched {
|
||||
return fmt.Errorf("String '%s' is not a valid UUID", input)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FormatUUID takes a string in input and return an UUID formatted string by repeating the string and placing dashes if necessary
|
||||
func FormatUUID(part string) (string, error) {
|
||||
if len(part) < 1 {
|
||||
return "", fmt.Errorf("Empty UUID")
|
||||
}
|
||||
if len(part) < 32 {
|
||||
part = strings.Repeat(part, 32)
|
||||
}
|
||||
if len(part) > 32 {
|
||||
part = part[:32]
|
||||
}
|
||||
uuid := part[:8] + "-" + part[8:12] + "-1" + part[13:16] + "-" + part[16:20] + "-" + part[20:32]
|
||||
|
||||
err := IsUUID(uuid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// GenerateRandomUUID returns an UUID based on random strings
|
||||
func GenerateRandomUUID(length int) (string, error) {
|
||||
var letters = []rune("abcdef0123456789")
|
||||
|
||||
b := make([]rune, length)
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return FormatUUID(string(b))
|
||||
}
|
||||
|
||||
// GenerateHexspeakUUID returns an UUID formatted string containing hexspeak words
|
||||
func GenerateHexspeakUUID(i int) (string, error) {
|
||||
if i < 0 {
|
||||
i = -i
|
||||
}
|
||||
hexspeaks := []string{
|
||||
"0ff1ce",
|
||||
"31337",
|
||||
"4b1d",
|
||||
"badc0de",
|
||||
"badcafe",
|
||||
"badf00d",
|
||||
"deadbabe",
|
||||
"deadbeef",
|
||||
"deadc0de",
|
||||
"deadfeed",
|
||||
"fee1bad",
|
||||
}
|
||||
return FormatUUID(hexspeaks[i%len(hexspeaks)])
|
||||
}
|
||||
|
||||
// GenerateLenUUID returns an UUID formatted string based on an index number
|
||||
func GenerateLenUUID(i int) (string, error) {
|
||||
if i < 0 {
|
||||
i = 2<<29 + i
|
||||
}
|
||||
return FormatUUID(fmt.Sprintf("%x", i))
|
||||
}
|
21
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/LICENSE
generated
vendored
21
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Peter Renström
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
43
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/README.md
generated
vendored
43
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/README.md
generated
vendored
@ -1,43 +0,0 @@
|
||||
# Fuzzy Search
|
||||
|
||||
[](https://travis-ci.org/renstrom/fuzzysearch)
|
||||
[](https://godoc.org/github.com/renstrom/fuzzysearch/fuzzy)
|
||||
|
||||
Inspired by _[bevacqua/fuzzysearch][1]_, a fuzzy matching library written in JavaScript. But contains some extras like ranking using _[Levenshtein distance][2]_ (see [`RankMatch()`](https://godoc.org/github.com/renstrom/fuzzysearch/fuzzy#RankMatch)) and finding matches in a list of words (see [`Find()`](https://godoc.org/github.com/renstrom/fuzzysearch/fuzzy#Find)).
|
||||
|
||||
Fuzzy searching allows for flexibly matching a string with partial input, useful for filtering data very quickly based on lightweight user input.
|
||||
|
||||
The current implementation uses the algorithm suggested by Mr. Aleph, a russian compiler engineer working at V8.
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
fuzzy.Match("twl", "cartwheel") // true
|
||||
fuzzy.Match("cart", "cartwheel") // true
|
||||
fuzzy.Match("cw", "cartwheel") // true
|
||||
fuzzy.Match("ee", "cartwheel") // true
|
||||
fuzzy.Match("art", "cartwheel") // true
|
||||
fuzzy.Match("eeel", "cartwheel") // false
|
||||
fuzzy.Match("dog", "cartwheel") // false
|
||||
|
||||
fuzzy.RankMatch("kitten", "sitting") // 3
|
||||
|
||||
words := []string{"cartwheel", "foobar", "wheel", "baz"}
|
||||
fuzzy.Find("whl", words) // [cartwheel wheel]
|
||||
|
||||
fuzzy.RankFind("whl", words) // [{whl cartwheel 6} {whl wheel 2}]
|
||||
```
|
||||
|
||||
You can sort the result of a `fuzzy.RankFind()` call using the [`sort`](https://golang.org/pkg/sort/) package in the standard library:
|
||||
|
||||
```go
|
||||
matches := fuzzy.RankFind("whl", words) // [{whl cartwheel 6} {whl wheel 2}]
|
||||
sort.Sort(matches) // [{whl wheel 2} {whl cartwheel 6}]
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
[1]: https://github.com/bevacqua/fuzzysearch
|
||||
[2]: http://en.wikipedia.org/wiki/Levenshtein_distance
|
167
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/fuzzy/fuzzy.go
generated
vendored
167
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/fuzzy/fuzzy.go
generated
vendored
@ -1,167 +0,0 @@
|
||||
// Fuzzy searching allows for flexibly matching a string with partial input,
|
||||
// useful for filtering data very quickly based on lightweight user input.
|
||||
package fuzzy
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var noop = func(r rune) rune { return r }
|
||||
|
||||
// Match returns true if source matches target using a fuzzy-searching
|
||||
// algorithm. Note that it doesn't implement Levenshtein distance (see
|
||||
// RankMatch instead), but rather a simplified version where there's no
|
||||
// approximation. The method will return true only if each character in the
|
||||
// source can be found in the target and occurs after the preceding matches.
|
||||
func Match(source, target string) bool {
|
||||
return match(source, target, noop)
|
||||
}
|
||||
|
||||
// MatchFold is a case-insensitive version of Match.
|
||||
func MatchFold(source, target string) bool {
|
||||
return match(source, target, unicode.ToLower)
|
||||
}
|
||||
|
||||
func match(source, target string, fn func(rune) rune) bool {
|
||||
lenDiff := len(target) - len(source)
|
||||
|
||||
if lenDiff < 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if lenDiff == 0 && source == target {
|
||||
return true
|
||||
}
|
||||
|
||||
Outer:
|
||||
for _, r1 := range source {
|
||||
for i, r2 := range target {
|
||||
if fn(r1) == fn(r2) {
|
||||
target = target[i+utf8.RuneLen(r2):]
|
||||
continue Outer
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Find will return a list of strings in targets that fuzzy matches source.
|
||||
func Find(source string, targets []string) []string {
|
||||
return find(source, targets, noop)
|
||||
}
|
||||
|
||||
// FindFold is a case-insensitive version of Find.
|
||||
func FindFold(source string, targets []string) []string {
|
||||
return find(source, targets, unicode.ToLower)
|
||||
}
|
||||
|
||||
func find(source string, targets []string, fn func(rune) rune) []string {
|
||||
var matches []string
|
||||
|
||||
for _, target := range targets {
|
||||
if match(source, target, fn) {
|
||||
matches = append(matches, target)
|
||||
}
|
||||
}
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
// RankMatch is similar to Match except it will measure the Levenshtein
|
||||
// distance between the source and the target and return its result. If there
|
||||
// was no match, it will return -1.
|
||||
// Given the requirements of match, RankMatch only needs to perform a subset of
|
||||
// the Levenshtein calculation, only deletions need be considered, required
|
||||
// additions and substitutions would fail the match test.
|
||||
func RankMatch(source, target string) int {
|
||||
return rank(source, target, noop)
|
||||
}
|
||||
|
||||
// RankMatchFold is a case-insensitive version of RankMatch.
|
||||
func RankMatchFold(source, target string) int {
|
||||
return rank(source, target, unicode.ToLower)
|
||||
}
|
||||
|
||||
func rank(source, target string, fn func(rune) rune) int {
|
||||
lenDiff := len(target) - len(source)
|
||||
|
||||
if lenDiff < 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
if lenDiff == 0 && source == target {
|
||||
return 0
|
||||
}
|
||||
|
||||
runeDiff := 0
|
||||
|
||||
Outer:
|
||||
for _, r1 := range source {
|
||||
for i, r2 := range target {
|
||||
if fn(r1) == fn(r2) {
|
||||
target = target[i+utf8.RuneLen(r2):]
|
||||
continue Outer
|
||||
} else {
|
||||
runeDiff++
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Count up remaining char
|
||||
for len(target) > 0 {
|
||||
target = target[utf8.RuneLen(rune(target[0])):]
|
||||
runeDiff++
|
||||
}
|
||||
|
||||
return runeDiff
|
||||
}
|
||||
|
||||
// RankFind is similar to Find, except it will also rank all matches using
|
||||
// Levenshtein distance.
|
||||
func RankFind(source string, targets []string) Ranks {
|
||||
var r Ranks
|
||||
for _, target := range find(source, targets, noop) {
|
||||
distance := LevenshteinDistance(source, target)
|
||||
r = append(r, Rank{source, target, distance})
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// RankFindFold is a case-insensitive version of RankFind.
|
||||
func RankFindFold(source string, targets []string) Ranks {
|
||||
var r Ranks
|
||||
for _, target := range find(source, targets, unicode.ToLower) {
|
||||
distance := LevenshteinDistance(source, target)
|
||||
r = append(r, Rank{source, target, distance})
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
type Rank struct {
|
||||
// Source is used as the source for matching.
|
||||
Source string
|
||||
|
||||
// Target is the word matched against.
|
||||
Target string
|
||||
|
||||
// Distance is the Levenshtein distance between Source and Target.
|
||||
Distance int
|
||||
}
|
||||
|
||||
type Ranks []Rank
|
||||
|
||||
func (r Ranks) Len() int {
|
||||
return len(r)
|
||||
}
|
||||
|
||||
func (r Ranks) Swap(i, j int) {
|
||||
r[i], r[j] = r[j], r[i]
|
||||
}
|
||||
|
||||
func (r Ranks) Less(i, j int) bool {
|
||||
return r[i].Distance < r[j].Distance
|
||||
}
|
43
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/fuzzy/levenshtein.go
generated
vendored
43
src/cmd/linuxkit/vendor/github.com/renstrom/fuzzysearch/fuzzy/levenshtein.go
generated
vendored
@ -1,43 +0,0 @@
|
||||
package fuzzy
|
||||
|
||||
// LevenshteinDistance measures the difference between two strings.
|
||||
// The Levenshtein distance between two words is the minimum number of
|
||||
// single-character edits (i.e. insertions, deletions or substitutions)
|
||||
// required to change one word into the other.
|
||||
//
|
||||
// This implemention is optimized to use O(min(m,n)) space and is based on the
|
||||
// optimized C version found here:
|
||||
// http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#C
|
||||
func LevenshteinDistance(s, t string) int {
|
||||
r1, r2 := []rune(s), []rune(t)
|
||||
column := make([]int, len(r1)+1)
|
||||
|
||||
for y := 1; y <= len(r1); y++ {
|
||||
column[y] = y
|
||||
}
|
||||
|
||||
for x := 1; x <= len(r2); x++ {
|
||||
column[0] = x
|
||||
|
||||
for y, lastDiag := 1, x-1; y <= len(r1); y++ {
|
||||
oldDiag := column[y]
|
||||
cost := 0
|
||||
if r1[y-1] != r2[x-1] {
|
||||
cost = 1
|
||||
}
|
||||
column[y] = min(column[y]+1, column[y-1]+1, lastDiag+cost)
|
||||
lastDiag = oldDiag
|
||||
}
|
||||
}
|
||||
|
||||
return column[len(r1)]
|
||||
}
|
||||
|
||||
func min(a, b, c int) int {
|
||||
if a < b && a < c {
|
||||
return a
|
||||
} else if b < c {
|
||||
return b
|
||||
}
|
||||
return c
|
||||
}
|
21
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/LICENSE
generated
vendored
21
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Scaleway
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
27
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/README.md
generated
vendored
27
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/README.md
generated
vendored
@ -1,27 +0,0 @@
|
||||
# Scaleway's API golang client
|
||||
|
||||
[](https://godoc.org/github.com/scaleway/go-scaleway)
|
||||
|
||||
This package contains facilities to play with the Scaleway API, it includes the following features:
|
||||
|
||||
- dedicated configuration file containing credentials to deal with the API
|
||||
- caching to resolve UUIDs without contacting the API
|
||||
|
||||
## Links
|
||||
|
||||
- [API documentation](https://developer.scaleway.com)
|
||||
- [Official Python SDK](https://github.com/scaleway/python-scaleway)
|
||||
- Projects using this SDK
|
||||
- https://github.com/scaleway/scaleway-cli
|
||||
- https://github.com/scaleway/devhub
|
||||
- https://github.com/scaleway/docker-machine-driver-scaleway
|
||||
- https://github.com/huseyin/docker-machine-driver-scaleway
|
||||
- https://github.com/scaleway-community/scaleway-ubuntu-coreos/blob/master/overlay/usr/local/update-firewall/scw-api/cache.go
|
||||
- https://github.com/pulcy/quark
|
||||
- https://github.com/hex-sh/terraform-provider-scaleway
|
||||
- https://github.com/tscolari/bosh-scaleway-cpi
|
||||
- Other **golang** clients
|
||||
- https://github.com/lalyos/onlabs
|
||||
- https://github.com/meatballhat/packer-builder-onlinelabs
|
||||
- https://github.com/nlamirault/go-scaleway
|
||||
- https://github.com/golang/build/blob/master/cmd/scaleway/scaleway.go
|
2003
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/api.go
generated
vendored
2003
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/api.go
generated
vendored
File diff suppressed because it is too large
Load Diff
693
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/cache/cache.go
generated
vendored
693
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/cache/cache.go
generated
vendored
@ -1,693 +0,0 @@
|
||||
// Copyright (C) 2018 Scaleway. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/moul/anonuuid"
|
||||
"github.com/renstrom/fuzzysearch/fuzzy"
|
||||
"github.com/scaleway/go-scaleway/types"
|
||||
)
|
||||
|
||||
const (
|
||||
// CacheRegion permits to access at the region field
|
||||
CacheRegion = iota
|
||||
// CacheArch permits to access at the arch field
|
||||
CacheArch
|
||||
// CacheOwner permits to access at the owner field
|
||||
CacheOwner
|
||||
// CacheTitle permits to access at the title field
|
||||
CacheTitle
|
||||
// CacheMarketPlaceUUID is used to determine the UUID of local images
|
||||
CacheMarketPlaceUUID
|
||||
// CacheMaxfield is used to determine the size of array
|
||||
CacheMaxfield
|
||||
)
|
||||
|
||||
// ScalewayCache is used not to query the API to resolve full identifiers
|
||||
type ScalewayCache struct {
|
||||
// Images contains names of Scaleway images indexed by identifier
|
||||
Images map[string][CacheMaxfield]string `json:"images"`
|
||||
|
||||
// Snapshots contains names of Scaleway snapshots indexed by identifier
|
||||
Snapshots map[string][CacheMaxfield]string `json:"snapshots"`
|
||||
|
||||
// Volumes contains names of Scaleway volumes indexed by identifier
|
||||
Volumes map[string][CacheMaxfield]string `json:"volumes"`
|
||||
|
||||
// Bootscripts contains names of Scaleway bootscripts indexed by identifier
|
||||
Bootscripts map[string][CacheMaxfield]string `json:"bootscripts"`
|
||||
|
||||
// Servers contains names of Scaleway servers indexed by identifier
|
||||
Servers map[string][CacheMaxfield]string `json:"servers"`
|
||||
|
||||
// Path is the path to the cache file
|
||||
Path string `json:"-"`
|
||||
|
||||
// Modified tells if the cache needs to be overwritten or not
|
||||
Modified bool `json:"-"`
|
||||
|
||||
// Lock allows ScalewayCache to be used concurrently
|
||||
Lock sync.Mutex `json:"-"`
|
||||
|
||||
hookSave func()
|
||||
}
|
||||
|
||||
// NewScalewayCache loads a per-user cache
|
||||
func NewScalewayCache(hookSave func()) (*ScalewayCache, error) {
|
||||
var cache ScalewayCache
|
||||
|
||||
cache.hookSave = hookSave
|
||||
homeDir := os.Getenv("HOME") // *nix
|
||||
if homeDir == "" { // Windows
|
||||
homeDir = os.Getenv("USERPROFILE")
|
||||
}
|
||||
if homeDir == "" {
|
||||
homeDir = "/tmp"
|
||||
}
|
||||
cachePath := filepath.Join(homeDir, ".scw-cache.db")
|
||||
cache.Path = cachePath
|
||||
_, err := os.Stat(cachePath)
|
||||
if os.IsNotExist(err) {
|
||||
cache.Clear()
|
||||
return &cache, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file, err := ioutil.ReadFile(cachePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(file, &cache)
|
||||
if err != nil {
|
||||
// fix compatibility with older version
|
||||
if err = os.Remove(cachePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cache.Clear()
|
||||
return &cache, nil
|
||||
}
|
||||
if cache.Images == nil {
|
||||
cache.Images = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
if cache.Snapshots == nil {
|
||||
cache.Snapshots = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
if cache.Volumes == nil {
|
||||
cache.Volumes = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
if cache.Servers == nil {
|
||||
cache.Servers = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
if cache.Bootscripts == nil {
|
||||
cache.Bootscripts = make(map[string][CacheMaxfield]string)
|
||||
}
|
||||
return &cache, nil
|
||||
}
|
||||
|
||||
// Clear removes all information from the cache
|
||||
func (c *ScalewayCache) Clear() {
|
||||
c.Images = make(map[string][CacheMaxfield]string)
|
||||
c.Snapshots = make(map[string][CacheMaxfield]string)
|
||||
c.Volumes = make(map[string][CacheMaxfield]string)
|
||||
c.Bootscripts = make(map[string][CacheMaxfield]string)
|
||||
c.Servers = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// Flush flushes the cache database
|
||||
func (c *ScalewayCache) Flush() error {
|
||||
return os.Remove(c.Path)
|
||||
}
|
||||
|
||||
// Save atomically overwrites the current cache database
|
||||
func (c *ScalewayCache) Save() error {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.hookSave()
|
||||
if c.Modified {
|
||||
file, err := ioutil.TempFile(filepath.Dir(c.Path), filepath.Base(c.Path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(file).Encode(c); err != nil {
|
||||
file.Close()
|
||||
os.Remove(file.Name())
|
||||
return err
|
||||
}
|
||||
|
||||
file.Close()
|
||||
if err := os.Rename(file.Name(), c.Path); err != nil {
|
||||
os.Remove(file.Name())
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ComputeRankMatch fills `ScalewayResolverResult.RankMatch` with its `fuzzy` score
|
||||
func ComputeRankMatch(s *types.ScalewayResolverResult, needle string) {
|
||||
s.Needle = needle
|
||||
s.RankMatch = fuzzy.RankMatch(needle, s.Name)
|
||||
}
|
||||
|
||||
// LookUpImages attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpImages(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Images[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
needle = regexp.MustCompile(`^user/`).ReplaceAllString(needle, "")
|
||||
// FIXME: if 'user/' is in needle, only watch for a user image
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Images {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
} else if strings.HasPrefix(fields[CacheMarketPlaceUUID], needle) || nameRegex.MatchString(fields[CacheMarketPlaceUUID]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// LookUpSnapshots attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpSnapshots(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Snapshots[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierSnapshot)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
needle = regexp.MustCompile(`^user/`).ReplaceAllString(needle, "")
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Snapshots {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierSnapshot)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierSnapshot)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// LookUpVolumes attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpVolumes(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Volumes[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierVolume)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Volumes {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierVolume)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierVolume)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// LookUpBootscripts attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpBootscripts(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Bootscripts[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierBootscript)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Bootscripts {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierBootscript)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierBootscript)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// LookUpServers attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpServers(needle string, acceptUUID bool) (types.ScalewayResolverResults, error) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
var res types.ScalewayResolverResults
|
||||
var exactMatches types.ScalewayResolverResults
|
||||
|
||||
if acceptUUID && anonuuid.IsUUID(needle) == nil {
|
||||
if fields, ok := c.Servers[needle]; ok {
|
||||
entry, err := types.NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierServer)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*"))
|
||||
for identifier, fields := range c.Servers {
|
||||
if fields[CacheTitle] == needle {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierServer)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
exactMatches = append(exactMatches, entry)
|
||||
}
|
||||
if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) {
|
||||
entry, err := types.NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], types.IdentifierServer)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
res = append(res, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if len(exactMatches) == 1 {
|
||||
return exactMatches, nil
|
||||
}
|
||||
|
||||
return removeDuplicatesResults(res), nil
|
||||
}
|
||||
|
||||
// removeDuplicatesResults transforms an array into a unique array
|
||||
func removeDuplicatesResults(elements types.ScalewayResolverResults) types.ScalewayResolverResults {
|
||||
encountered := map[string]types.ScalewayResolverResult{}
|
||||
|
||||
// Create a map of all unique elements.
|
||||
for v := range elements {
|
||||
encountered[elements[v].Identifier] = elements[v]
|
||||
}
|
||||
|
||||
// Place all keys from the map into a slice.
|
||||
results := types.ScalewayResolverResults{}
|
||||
for _, result := range encountered {
|
||||
results = append(results, result)
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// LookUpIdentifiers attempts to return identifiers matching a pattern
|
||||
func (c *ScalewayCache) LookUpIdentifiers(needle string) (types.ScalewayResolverResults, error) {
|
||||
results := types.ScalewayResolverResults{}
|
||||
|
||||
identifierType, needle := types.ParseNeedle(needle)
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierServer) > 0 {
|
||||
servers, err := c.LookUpServers(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range servers {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierServer)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierImage) > 0 {
|
||||
images, err := c.LookUpImages(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range images {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierImage)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierSnapshot) > 0 {
|
||||
snapshots, err := c.LookUpSnapshots(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range snapshots {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierSnapshot)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierVolume) > 0 {
|
||||
volumes, err := c.LookUpVolumes(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range volumes {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierVolume)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if identifierType&(types.IdentifierUnknown|types.IdentifierBootscript) > 0 {
|
||||
bootscripts, err := c.LookUpBootscripts(needle, false)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
for _, result := range bootscripts {
|
||||
entry, err := types.NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, types.IdentifierBootscript)
|
||||
if err != nil {
|
||||
return types.ScalewayResolverResults{}, err
|
||||
}
|
||||
ComputeRankMatch(&entry, needle)
|
||||
results = append(results, entry)
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// InsertServer registers a server in the cache
|
||||
func (c *ScalewayCache) InsertServer(identifier, region, arch, owner, name string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Servers[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Servers[identifier] = [CacheMaxfield]string{region, arch, owner, name}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveServer removes a server from the cache
|
||||
func (c *ScalewayCache) RemoveServer(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Servers, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearServers removes all servers from the cache
|
||||
func (c *ScalewayCache) ClearServers() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Servers = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// InsertImage registers an image in the cache
|
||||
func (c *ScalewayCache) InsertImage(identifier, region, arch, owner, name, marketPlaceUUID string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Images[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Images[identifier] = [CacheMaxfield]string{region, arch, owner, name, marketPlaceUUID}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveImage removes a server from the cache
|
||||
func (c *ScalewayCache) RemoveImage(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Images, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearImages removes all images from the cache
|
||||
func (c *ScalewayCache) ClearImages() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Images = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// InsertSnapshot registers an snapshot in the cache
|
||||
func (c *ScalewayCache) InsertSnapshot(identifier, region, arch, owner, name string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Snapshots[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Snapshots[identifier] = [CacheMaxfield]string{region, arch, owner, name}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveSnapshot removes a server from the cache
|
||||
func (c *ScalewayCache) RemoveSnapshot(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Snapshots, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearSnapshots removes all snapshots from the cache
|
||||
func (c *ScalewayCache) ClearSnapshots() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Snapshots = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// InsertVolume registers an volume in the cache
|
||||
func (c *ScalewayCache) InsertVolume(identifier, region, arch, owner, name string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Volumes[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Volumes[identifier] = [CacheMaxfield]string{region, arch, owner, name}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveVolume removes a server from the cache
|
||||
func (c *ScalewayCache) RemoveVolume(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Volumes, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearVolumes removes all volumes from the cache
|
||||
func (c *ScalewayCache) ClearVolumes() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Volumes = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// InsertBootscript registers an bootscript in the cache
|
||||
func (c *ScalewayCache) InsertBootscript(identifier, region, arch, owner, name string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
fields, exists := c.Bootscripts[identifier]
|
||||
if !exists || fields[CacheTitle] != name {
|
||||
c.Bootscripts[identifier] = [CacheMaxfield]string{region, arch, owner, name}
|
||||
c.Modified = true
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveBootscript removes a bootscript from the cache
|
||||
func (c *ScalewayCache) RemoveBootscript(identifier string) {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
delete(c.Bootscripts, identifier)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// ClearBootscripts removes all bootscripts from the cache
|
||||
func (c *ScalewayCache) ClearBootscripts() {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
c.Bootscripts = make(map[string][CacheMaxfield]string)
|
||||
c.Modified = true
|
||||
}
|
||||
|
||||
// GetNbServers returns the number of servers in the cache
|
||||
func (c *ScalewayCache) GetNbServers() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Servers)
|
||||
}
|
||||
|
||||
// GetNbImages returns the number of images in the cache
|
||||
func (c *ScalewayCache) GetNbImages() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Images)
|
||||
}
|
||||
|
||||
// GetNbSnapshots returns the number of snapshots in the cache
|
||||
func (c *ScalewayCache) GetNbSnapshots() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Snapshots)
|
||||
}
|
||||
|
||||
// GetNbVolumes returns the number of volumes in the cache
|
||||
func (c *ScalewayCache) GetNbVolumes() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Volumes)
|
||||
}
|
||||
|
||||
// GetNbBootscripts returns the number of bootscripts in the cache
|
||||
func (c *ScalewayCache) GetNbBootscripts() int {
|
||||
c.Lock.Lock()
|
||||
defer c.Lock.Unlock()
|
||||
|
||||
return len(c.Bootscripts)
|
||||
}
|
77
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/logger/logger.go
generated
vendored
77
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/logger/logger.go
generated
vendored
@ -1,77 +0,0 @@
|
||||
// Copyright (C) 2018 Scaleway. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Logger handles logging concerns for the Scaleway API SDK
|
||||
type Logger interface {
|
||||
LogHTTP(*http.Request)
|
||||
Fatalf(format string, v ...interface{})
|
||||
Debugf(format string, v ...interface{})
|
||||
Infof(format string, v ...interface{})
|
||||
Warnf(format string, v ...interface{})
|
||||
}
|
||||
|
||||
// NewDefaultLogger returns a logger which is configured for stdout
|
||||
func NewDefaultLogger() Logger {
|
||||
return &defaultLogger{
|
||||
Logger: log.New(os.Stdout, "", log.LstdFlags),
|
||||
}
|
||||
}
|
||||
|
||||
type defaultLogger struct {
|
||||
*log.Logger
|
||||
}
|
||||
|
||||
func (l *defaultLogger) LogHTTP(r *http.Request) {
|
||||
l.Printf("%s %s\n", r.Method, r.URL.RawPath)
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Fatalf(format string, v ...interface{}) {
|
||||
l.Printf("[FATAL] %s\n", fmt.Sprintf(format, v))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Debugf(format string, v ...interface{}) {
|
||||
l.Printf("[DEBUG] %s\n", fmt.Sprintf(format, v))
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Infof(format string, v ...interface{}) {
|
||||
l.Printf("[INFO ] %s\n", fmt.Sprintf(format, v))
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Warnf(format string, v ...interface{}) {
|
||||
l.Printf("[WARN ] %s\n", fmt.Sprintf(format, v))
|
||||
}
|
||||
|
||||
type disableLogger struct {
|
||||
}
|
||||
|
||||
// NewDisableLogger returns a logger which is configured to do nothing
|
||||
func NewDisableLogger() Logger {
|
||||
return &disableLogger{}
|
||||
}
|
||||
|
||||
func (d *disableLogger) LogHTTP(r *http.Request) {
|
||||
}
|
||||
|
||||
func (d *disableLogger) Fatalf(format string, v ...interface{}) {
|
||||
panic(fmt.Sprintf(format, v))
|
||||
}
|
||||
|
||||
func (d *disableLogger) Debugf(format string, v ...interface{}) {
|
||||
}
|
||||
|
||||
func (d *disableLogger) Infof(format string, v ...interface{}) {
|
||||
}
|
||||
|
||||
func (d *disableLogger) Warnf(format string, v ...interface{}) {
|
||||
}
|
983
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/types/types.go
generated
vendored
983
src/cmd/linuxkit/vendor/github.com/scaleway/go-scaleway/types/types.go
generated
vendored
@ -1,983 +0,0 @@
|
||||
// Copyright (C) 2018 Scaleway. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/moul/anonuuid"
|
||||
)
|
||||
|
||||
// ParseNeedle parses a user needle and try to extract a forced object type
|
||||
// i.e:
|
||||
// - server:blah-blah -> kind=server, needle=blah-blah
|
||||
// - blah-blah -> kind="", needle=blah-blah
|
||||
// - not-existing-type:blah-blah
|
||||
func ParseNeedle(input string) (identifierType int, needle string) {
|
||||
parts := strings.Split(input, ":")
|
||||
if len(parts) == 2 {
|
||||
switch parts[0] {
|
||||
case "server":
|
||||
return IdentifierServer, parts[1]
|
||||
case "image":
|
||||
return IdentifierImage, parts[1]
|
||||
case "snapshot":
|
||||
return IdentifierSnapshot, parts[1]
|
||||
case "bootscript":
|
||||
return IdentifierBootscript, parts[1]
|
||||
case "volume":
|
||||
return IdentifierVolume, parts[1]
|
||||
}
|
||||
}
|
||||
return IdentifierUnknown, input
|
||||
}
|
||||
|
||||
const (
|
||||
// IdentifierUnknown is used when we don't know explicitly the type key of the object (used for nil comparison)
|
||||
IdentifierUnknown = 1 << iota
|
||||
// IdentifierServer is the type key of cached server objects
|
||||
IdentifierServer
|
||||
// IdentifierImage is the type key of cached image objects
|
||||
IdentifierImage
|
||||
// IdentifierSnapshot is the type key of cached snapshot objects
|
||||
IdentifierSnapshot
|
||||
// IdentifierBootscript is the type key of cached bootscript objects
|
||||
IdentifierBootscript
|
||||
// IdentifierVolume is the type key of cached volume objects
|
||||
IdentifierVolume
|
||||
)
|
||||
|
||||
// ScalewayResolverResult is a structure containing human-readable information
|
||||
// about resolver results. This structure is used to display the user choices.
|
||||
type ScalewayResolverResult struct {
|
||||
Identifier string
|
||||
Type int
|
||||
Name string
|
||||
Arch string
|
||||
Needle string
|
||||
RankMatch int
|
||||
Region string
|
||||
}
|
||||
|
||||
// ScalewayResolverResults is a list of `ScalewayResolverResult`
|
||||
type ScalewayResolverResults []ScalewayResolverResult
|
||||
|
||||
// NewScalewayResolverResult returns a new ScalewayResolverResult
|
||||
func NewScalewayResolverResult(Identifier, Name, Arch, Region string, Type int) (ScalewayResolverResult, error) {
|
||||
if err := anonuuid.IsUUID(Identifier); err != nil {
|
||||
return ScalewayResolverResult{}, err
|
||||
}
|
||||
return ScalewayResolverResult{
|
||||
Identifier: Identifier,
|
||||
Type: Type,
|
||||
Name: Name,
|
||||
Arch: Arch,
|
||||
Region: Region,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s ScalewayResolverResults) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s ScalewayResolverResults) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s ScalewayResolverResults) Less(i, j int) bool {
|
||||
return s[i].RankMatch < s[j].RankMatch
|
||||
}
|
||||
|
||||
// TruncIdentifier returns first 8 characters of an Identifier (UUID)
|
||||
func (s *ScalewayResolverResult) TruncIdentifier() string {
|
||||
return s.Identifier[:8]
|
||||
}
|
||||
|
||||
func identifierTypeName(kind int) string {
|
||||
switch kind {
|
||||
case IdentifierServer:
|
||||
return "Server"
|
||||
case IdentifierImage:
|
||||
return "Image"
|
||||
case IdentifierSnapshot:
|
||||
return "Snapshot"
|
||||
case IdentifierVolume:
|
||||
return "Volume"
|
||||
case IdentifierBootscript:
|
||||
return "Bootscript"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// CodeName returns a full resource name with typed prefix
|
||||
func (s *ScalewayResolverResult) CodeName() string {
|
||||
name := strings.ToLower(s.Name)
|
||||
name = regexp.MustCompile(`[^a-z0-9-]`).ReplaceAllString(name, "-")
|
||||
name = regexp.MustCompile(`--+`).ReplaceAllString(name, "-")
|
||||
name = strings.Trim(name, "-")
|
||||
|
||||
return fmt.Sprintf("%s:%s", strings.ToLower(identifierTypeName(s.Type)), name)
|
||||
}
|
||||
|
||||
// FilterByArch deletes the elements which not match with arch
|
||||
func (s *ScalewayResolverResults) FilterByArch(arch string) {
|
||||
REDO:
|
||||
for i := range *s {
|
||||
if (*s)[i].Arch != arch {
|
||||
(*s)[i] = (*s)[len(*s)-1]
|
||||
*s = (*s)[:len(*s)-1]
|
||||
goto REDO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ScalewayAPIError represents a Scaleway API Error
|
||||
type ScalewayAPIError struct {
|
||||
// Message is a human-friendly error message
|
||||
APIMessage string `json:"message,omitempty"`
|
||||
|
||||
// Type is a string code that defines the kind of error
|
||||
Type string `json:"type,omitempty"`
|
||||
|
||||
// Fields contains detail about validation error
|
||||
Fields map[string][]string `json:"fields,omitempty"`
|
||||
|
||||
// StatusCode is the HTTP status code received
|
||||
StatusCode int `json:"-"`
|
||||
|
||||
// Message
|
||||
Message string `json:"-"`
|
||||
}
|
||||
|
||||
// Error returns a string representing the error
|
||||
func (e ScalewayAPIError) Error() string {
|
||||
var b bytes.Buffer
|
||||
|
||||
fmt.Fprintf(&b, "StatusCode: %v, ", e.StatusCode)
|
||||
fmt.Fprintf(&b, "Type: %v, ", e.Type)
|
||||
fmt.Fprintf(&b, "APIMessage: \x1b[31m%v\x1b[0m", e.APIMessage)
|
||||
if len(e.Fields) > 0 {
|
||||
fmt.Fprintf(&b, ", Details: %v", e.Fields)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// ScalewayIPAddress represents a Scaleway IP address
|
||||
type ScalewayIPAddress struct {
|
||||
// Identifier is a unique identifier for the IP address
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// IP is an IPv4 address
|
||||
IP string `json:"address,omitempty"`
|
||||
|
||||
// Dynamic is a flag that defines an IP that change on each reboot
|
||||
Dynamic *bool `json:"dynamic,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayVolume represents a Scaleway Volume
|
||||
type ScalewayVolume struct {
|
||||
// Identifier is a unique identifier for the volume
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Size is the allocated size of the volume
|
||||
Size uint64 `json:"size,omitempty"`
|
||||
|
||||
// CreationDate is the creation date of the volume
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// ModificationDate is the date of the last modification of the volume
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
|
||||
// Organization is the organization owning the volume
|
||||
Organization string `json:"organization,omitempty"`
|
||||
|
||||
// Name is the name of the volume
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Server is the server using this image
|
||||
Server *struct {
|
||||
Identifier string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
} `json:"server,omitempty"`
|
||||
|
||||
// VolumeType is a Scaleway identifier for the kind of volume (default: l_ssd)
|
||||
VolumeType string `json:"volume_type,omitempty"`
|
||||
|
||||
// ExportURI represents the url used by initrd/scripts to attach the volume
|
||||
ExportURI string `json:"export_uri,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneVolume represents the response of a GET /volumes/UUID API call
|
||||
type ScalewayOneVolume struct {
|
||||
Volume ScalewayVolume `json:"volume,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayVolumes represents a group of Scaleway volumes
|
||||
type ScalewayVolumes struct {
|
||||
// Volumes holds scaleway volumes of the response
|
||||
Volumes []ScalewayVolume `json:"volumes,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayVolumeDefinition represents a Scaleway volume definition
|
||||
type ScalewayVolumeDefinition struct {
|
||||
// Name is the user-defined name of the volume
|
||||
Name string `json:"name"`
|
||||
|
||||
// Image is the image used by the volume
|
||||
Size uint64 `json:"size"`
|
||||
|
||||
// Bootscript is the bootscript used by the volume
|
||||
Type string `json:"volume_type"`
|
||||
|
||||
// Organization is the owner of the volume
|
||||
Organization string `json:"organization"`
|
||||
}
|
||||
|
||||
// ScalewayVolumePutDefinition represents a Scaleway volume with nullable fields (for PUT)
|
||||
type ScalewayVolumePutDefinition struct {
|
||||
Identifier *string `json:"id,omitempty"`
|
||||
Size *uint64 `json:"size,omitempty"`
|
||||
CreationDate *string `json:"creation_date,omitempty"`
|
||||
ModificationDate *string `json:"modification_date,omitempty"`
|
||||
Organization *string `json:"organization,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Server struct {
|
||||
Identifier *string `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
} `json:"server,omitempty"`
|
||||
VolumeType *string `json:"volume_type,omitempty"`
|
||||
ExportURI *string `json:"export_uri,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayImage represents a Scaleway Image
|
||||
type ScalewayImage struct {
|
||||
// Identifier is a unique identifier for the image
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Name is a user-defined name for the image
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// CreationDate is the creation date of the image
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// ModificationDate is the date of the last modification of the image
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
|
||||
// RootVolume is the root volume bound to the image
|
||||
RootVolume ScalewayVolume `json:"root_volume,omitempty"`
|
||||
|
||||
// Public is true for public images and false for user images
|
||||
Public bool `json:"public,omitempty"`
|
||||
|
||||
// Bootscript is the bootscript bound to the image
|
||||
DefaultBootscript *ScalewayBootscript `json:"default_bootscript,omitempty"`
|
||||
|
||||
// Organization is the owner of the image
|
||||
Organization string `json:"organization,omitempty"`
|
||||
|
||||
// Arch is the architecture target of the image
|
||||
Arch string `json:"arch,omitempty"`
|
||||
|
||||
// FIXME: extra_volumes
|
||||
}
|
||||
|
||||
// ScalewayImageIdentifier represents a Scaleway Image Identifier
|
||||
type ScalewayImageIdentifier struct {
|
||||
Identifier string
|
||||
Arch string
|
||||
Region string
|
||||
Owner string
|
||||
}
|
||||
|
||||
// ScalewayOneImage represents the response of a GET /images/UUID API call
|
||||
type ScalewayOneImage struct {
|
||||
Image ScalewayImage `json:"image,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayImages represents a group of Scaleway images
|
||||
type ScalewayImages struct {
|
||||
// Images holds scaleway images of the response
|
||||
Images []ScalewayImage `json:"images,omitempty"`
|
||||
}
|
||||
|
||||
// ProductNetworkInterface gives interval and external allowed bandwidth
|
||||
type ProductNetworkInterface struct {
|
||||
InternalBandwidth uint64 `json:"internal_bandwidth,omitempty"`
|
||||
InternetBandwidth uint64 `json:"internet_bandwidth,omitempty"`
|
||||
}
|
||||
|
||||
// ProductNetwork lists all the network interfaces
|
||||
type ProductNetwork struct {
|
||||
Interfaces []ProductNetworkInterface `json:"interfaces,omitempty"`
|
||||
TotalInternalBandwidth uint64 `json:"sum_internal_bandwidth,omitempty"`
|
||||
TotalInternetBandwidth uint64 `json:"sum_internet_bandwidth,omitempty"`
|
||||
IPv6_Support bool `json:"ipv6_support,omitempty"`
|
||||
}
|
||||
|
||||
// ProductVolumeConstraint contains any volume constraint that the offer has
|
||||
type ProductVolumeConstraint struct {
|
||||
MinSize uint64 `json:"min_size,omitempty"`
|
||||
MaxSize uint64 `json:"max_size,omitempty"`
|
||||
}
|
||||
|
||||
// ProductServerOffer represents a specific offer
|
||||
type ProductServer struct {
|
||||
Arch string `json:"arch,omitempty"`
|
||||
Ncpus uint64 `json:"ncpus,omitempty"`
|
||||
Ram uint64 `json:"ram,omitempty"`
|
||||
Baremetal bool `json:"baremetal,omitempty"`
|
||||
VolumesConstraint ProductVolumeConstraint `json:"volumes_constraint,omitempty"`
|
||||
AltNames []string `json:"alt_names,omitempty"`
|
||||
Network ProductNetwork `json:"network,omitempty"`
|
||||
}
|
||||
|
||||
// Products holds a map of all Scaleway servers
|
||||
type ScalewayProductsServers struct {
|
||||
Servers map[string]ProductServer `json:"servers"`
|
||||
}
|
||||
|
||||
// ScalewaySnapshot represents a Scaleway Snapshot
|
||||
type ScalewaySnapshot struct {
|
||||
// Identifier is a unique identifier for the snapshot
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Name is a user-defined name for the snapshot
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// CreationDate is the creation date of the snapshot
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// ModificationDate is the date of the last modification of the snapshot
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
|
||||
// Size is the allocated size of the volume
|
||||
Size uint64 `json:"size,omitempty"`
|
||||
|
||||
// Organization is the owner of the snapshot
|
||||
Organization string `json:"organization"`
|
||||
|
||||
// State is the current state of the snapshot
|
||||
State string `json:"state"`
|
||||
|
||||
// VolumeType is the kind of volume behind the snapshot
|
||||
VolumeType string `json:"volume_type"`
|
||||
|
||||
// BaseVolume is the volume from which the snapshot inherits
|
||||
BaseVolume ScalewayVolume `json:"base_volume,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneSnapshot represents the response of a GET /snapshots/UUID API call
|
||||
type ScalewayOneSnapshot struct {
|
||||
Snapshot ScalewaySnapshot `json:"snapshot,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewaySnapshots represents a group of Scaleway snapshots
|
||||
type ScalewaySnapshots struct {
|
||||
// Snapshots holds scaleway snapshots of the response
|
||||
Snapshots []ScalewaySnapshot `json:"snapshots,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayBootscript represents a Scaleway Bootscript
|
||||
type ScalewayBootscript struct {
|
||||
Bootcmdargs string `json:"bootcmdargs,omitempty"`
|
||||
Dtb string `json:"dtb,omitempty"`
|
||||
Initrd string `json:"initrd,omitempty"`
|
||||
Kernel string `json:"kernel,omitempty"`
|
||||
|
||||
// Arch is the architecture target of the bootscript
|
||||
Arch string `json:"architecture,omitempty"`
|
||||
|
||||
// Identifier is a unique identifier for the bootscript
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Organization is the owner of the bootscript
|
||||
Organization string `json:"organization,omitempty"`
|
||||
|
||||
// Name is a user-defined name for the bootscript
|
||||
Title string `json:"title,omitempty"`
|
||||
|
||||
// Public is true for public bootscripts and false for user bootscripts
|
||||
Public bool `json:"public,omitempty"`
|
||||
|
||||
Default bool `json:"default,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneBootscript represents the response of a GET /bootscripts/UUID API call
|
||||
type ScalewayOneBootscript struct {
|
||||
Bootscript ScalewayBootscript `json:"bootscript,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayBootscripts represents a group of Scaleway bootscripts
|
||||
type ScalewayBootscripts struct {
|
||||
// Bootscripts holds Scaleway bootscripts of the response
|
||||
Bootscripts []ScalewayBootscript `json:"bootscripts,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayTask represents a Scaleway Task
|
||||
type ScalewayTask struct {
|
||||
// Identifier is a unique identifier for the task
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// StartDate is the start date of the task
|
||||
StartDate string `json:"started_at,omitempty"`
|
||||
|
||||
// TerminationDate is the termination date of the task
|
||||
TerminationDate string `json:"terminated_at,omitempty"`
|
||||
|
||||
HrefFrom string `json:"href_from,omitempty"`
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
Status string `json:"status,omitempty"`
|
||||
|
||||
Progress int `json:"progress,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneTask represents the response of a GET /tasks/UUID API call
|
||||
type ScalewayOneTask struct {
|
||||
Task ScalewayTask `json:"task,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayTasks represents a group of Scaleway tasks
|
||||
type ScalewayTasks struct {
|
||||
// Tasks holds scaleway tasks of the response
|
||||
Tasks []ScalewayTask `json:"tasks,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewaySecurityGroupRule definition
|
||||
type ScalewaySecurityGroupRule struct {
|
||||
Direction string `json:"direction"`
|
||||
Protocol string `json:"protocol"`
|
||||
IPRange string `json:"ip_range"`
|
||||
DestPortFrom int `json:"dest_port_from,omitempty"`
|
||||
Action string `json:"action"`
|
||||
Position int `json:"position"`
|
||||
DestPortTo string `json:"dest_port_to"`
|
||||
Editable bool `json:"editable"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// ScalewayGetSecurityGroupRules represents the response of a GET /security_group/{groupID}/rules
|
||||
type ScalewayGetSecurityGroupRules struct {
|
||||
Rules []ScalewaySecurityGroupRule `json:"rules"`
|
||||
}
|
||||
|
||||
// ScalewayGetSecurityGroupRule represents the response of a GET /security_group/{groupID}/rules/{ruleID}
|
||||
type ScalewayGetSecurityGroupRule struct {
|
||||
Rules ScalewaySecurityGroupRule `json:"rule"`
|
||||
}
|
||||
|
||||
// ScalewayNewSecurityGroupRule definition POST/PUT request /security_group/{groupID}
|
||||
type ScalewayNewSecurityGroupRule struct {
|
||||
Action string `json:"action"`
|
||||
Direction string `json:"direction"`
|
||||
IPRange string `json:"ip_range"`
|
||||
Protocol string `json:"protocol"`
|
||||
DestPortFrom int `json:"dest_port_from,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewaySecurityGroups definition
|
||||
type ScalewaySecurityGroups struct {
|
||||
Description string `json:"description"`
|
||||
ID string `json:"id"`
|
||||
Organization string `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Servers []ScalewaySecurityGroup `json:"servers"`
|
||||
EnableDefaultSecurity bool `json:"enable_default_security"`
|
||||
OrganizationDefault bool `json:"organization_default"`
|
||||
}
|
||||
|
||||
// ScalewayGetSecurityGroups represents the response of a GET /security_groups/
|
||||
type ScalewayGetSecurityGroups struct {
|
||||
SecurityGroups []ScalewaySecurityGroups `json:"security_groups"`
|
||||
}
|
||||
|
||||
// ScalewayGetSecurityGroup represents the response of a GET /security_groups/{groupID}
|
||||
type ScalewayGetSecurityGroup struct {
|
||||
SecurityGroups ScalewaySecurityGroups `json:"security_group"`
|
||||
}
|
||||
|
||||
// ScalewayIPDefinition represents the IP's fields
|
||||
type ScalewayIPDefinition struct {
|
||||
Organization string `json:"organization"`
|
||||
Reverse *string `json:"reverse"`
|
||||
ID string `json:"id"`
|
||||
Server *struct {
|
||||
Identifier string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
} `json:"server"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
// ScalewayGetIPS represents the response of a GET /ips/
|
||||
type ScalewayGetIPS struct {
|
||||
IPS []ScalewayIPDefinition `json:"ips"`
|
||||
}
|
||||
|
||||
// ScalewayGetIP represents the response of a GET /ips/{id_ip}
|
||||
type ScalewayGetIP struct {
|
||||
IP ScalewayIPDefinition `json:"ip"`
|
||||
}
|
||||
|
||||
// ScalewaySecurityGroup represents a Scaleway security group
|
||||
type ScalewaySecurityGroup struct {
|
||||
// Identifier is a unique identifier for the security group
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Name is the user-defined name of the security group
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayNewSecurityGroup definition POST request /security_groups
|
||||
type ScalewayNewSecurityGroup struct {
|
||||
Organization string `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// ScalewayUpdateSecurityGroup definition PUT request /security_groups
|
||||
type ScalewayUpdateSecurityGroup struct {
|
||||
Organization string `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
OrganizationDefault bool `json:"organization_default"`
|
||||
}
|
||||
|
||||
// ScalewayServer represents a Scaleway server
|
||||
type ScalewayServer struct {
|
||||
// Arch is the architecture target of the server
|
||||
Arch string `json:"arch,omitempty"`
|
||||
|
||||
// Identifier is a unique identifier for the server
|
||||
Identifier string `json:"id,omitempty"`
|
||||
|
||||
// Name is the user-defined name of the server
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// CreationDate is the creation date of the server
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// ModificationDate is the date of the last modification of the server
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
|
||||
// Image is the image used by the server
|
||||
Image ScalewayImage `json:"image,omitempty"`
|
||||
|
||||
// DynamicIPRequired is a flag that defines a server with a dynamic ip address attached
|
||||
DynamicIPRequired *bool `json:"dynamic_ip_required,omitempty"`
|
||||
|
||||
// PublicIP is the public IP address bound to the server
|
||||
PublicAddress ScalewayIPAddress `json:"public_ip,omitempty"`
|
||||
|
||||
// State is the current status of the server
|
||||
State string `json:"state,omitempty"`
|
||||
|
||||
// StateDetail is the detailed status of the server
|
||||
StateDetail string `json:"state_detail,omitempty"`
|
||||
|
||||
// PrivateIP represents the private IPV4 attached to the server (changes on each boot)
|
||||
PrivateIP string `json:"private_ip,omitempty"`
|
||||
|
||||
// Bootscript is the unique identifier of the selected bootscript
|
||||
Bootscript *ScalewayBootscript `json:"bootscript,omitempty"`
|
||||
|
||||
// Hostname represents the ServerName in a format compatible with unix's hostname
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
|
||||
// Tags represents user-defined tags
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
|
||||
// Volumes are the attached volumes
|
||||
Volumes map[string]ScalewayVolume `json:"volumes,omitempty"`
|
||||
|
||||
// SecurityGroup is the selected security group object
|
||||
SecurityGroup ScalewaySecurityGroup `json:"security_group,omitempty"`
|
||||
|
||||
// Organization is the owner of the server
|
||||
Organization string `json:"organization,omitempty"`
|
||||
|
||||
// CommercialType is the commercial type of the server (i.e: C1, C2[SML], VC1S)
|
||||
CommercialType string `json:"commercial_type,omitempty"`
|
||||
|
||||
// Location of the server
|
||||
Location struct {
|
||||
Platform string `json:"platform_id,omitempty"`
|
||||
Chassis string `json:"chassis_id,omitempty"`
|
||||
Cluster string `json:"cluster_id,omitempty"`
|
||||
Hypervisor string `json:"hypervisor_id,omitempty"`
|
||||
Blade string `json:"blade_id,omitempty"`
|
||||
Node string `json:"node_id,omitempty"`
|
||||
ZoneID string `json:"zone_id,omitempty"`
|
||||
} `json:"location,omitempty"`
|
||||
|
||||
IPV6 *ScalewayIPV6Definition `json:"ipv6,omitempty"`
|
||||
|
||||
EnableIPV6 bool `json:"enable_ipv6,omitempty"`
|
||||
|
||||
// This fields are not returned by the API, we generate it
|
||||
DNSPublic string `json:"dns_public,omitempty"`
|
||||
DNSPrivate string `json:"dns_private,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayIPV6Definition represents a Scaleway ipv6
|
||||
type ScalewayIPV6Definition struct {
|
||||
Netmask string `json:"netmask"`
|
||||
Gateway string `json:"gateway"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
// ScalewayServerPatchDefinition represents a Scaleway server with nullable fields (for PATCH)
|
||||
type ScalewayServerPatchDefinition struct {
|
||||
Arch *string `json:"arch,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
CreationDate *string `json:"creation_date,omitempty"`
|
||||
ModificationDate *string `json:"modification_date,omitempty"`
|
||||
Image *ScalewayImage `json:"image,omitempty"`
|
||||
DynamicIPRequired *bool `json:"dynamic_ip_required,omitempty"`
|
||||
PublicAddress *ScalewayIPAddress `json:"public_ip,omitempty"`
|
||||
State *string `json:"state,omitempty"`
|
||||
StateDetail *string `json:"state_detail,omitempty"`
|
||||
PrivateIP *string `json:"private_ip,omitempty"`
|
||||
Bootscript *string `json:"bootscript,omitempty"`
|
||||
Hostname *string `json:"hostname,omitempty"`
|
||||
Volumes *map[string]ScalewayVolume `json:"volumes,omitempty"`
|
||||
SecurityGroup *ScalewaySecurityGroup `json:"security_group,omitempty"`
|
||||
Organization *string `json:"organization,omitempty"`
|
||||
Tags *[]string `json:"tags,omitempty"`
|
||||
IPV6 *ScalewayIPV6Definition `json:"ipv6,omitempty"`
|
||||
EnableIPV6 *bool `json:"enable_ipv6,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayServerDefinition represents a Scaleway server with image definition
|
||||
type ScalewayServerDefinition struct {
|
||||
// Name is the user-defined name of the server
|
||||
Name string `json:"name"`
|
||||
|
||||
// Image is the image used by the server
|
||||
Image *string `json:"image,omitempty"`
|
||||
|
||||
// Volumes are the attached volumes
|
||||
Volumes map[string]string `json:"volumes,omitempty"`
|
||||
|
||||
// DynamicIPRequired is a flag that defines a server with a dynamic ip address attached
|
||||
DynamicIPRequired *bool `json:"dynamic_ip_required,omitempty"`
|
||||
|
||||
// BootType defines the type of boot
|
||||
BootType string `json:"boot_type,omitempty"`
|
||||
|
||||
// Bootscript is the bootscript used by the server
|
||||
Bootscript *string `json:"bootscript"`
|
||||
|
||||
// Tags are the metadata tags attached to the server
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
|
||||
// Organization is the owner of the server
|
||||
Organization string `json:"organization"`
|
||||
|
||||
// CommercialType is the commercial type of the server (i.e: C1, C2[SML], VC1S)
|
||||
CommercialType string `json:"commercial_type"`
|
||||
|
||||
PublicIP string `json:"public_ip,omitempty"`
|
||||
|
||||
EnableIPV6 bool `json:"enable_ipv6,omitempty"`
|
||||
|
||||
SecurityGroup string `json:"security_group,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayOneServer represents the response of a GET /servers/UUID API call
|
||||
type ScalewayOneServer struct {
|
||||
Server ScalewayServer `json:"server,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayServers represents a group of Scaleway servers
|
||||
type ScalewayServers struct {
|
||||
// Servers holds scaleway servers of the response
|
||||
Servers []ScalewayServer `json:"servers,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayServerAction represents an action to perform on a Scaleway server
|
||||
type ScalewayServerAction struct {
|
||||
// Action is the name of the action to trigger
|
||||
Action string `json:"action,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewaySnapshotDefinition represents a Scaleway snapshot definition
|
||||
type ScalewaySnapshotDefinition struct {
|
||||
VolumeIDentifier string `json:"volume_id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Organization string `json:"organization"`
|
||||
}
|
||||
|
||||
// ScalewayImageDefinition represents a Scaleway image definition
|
||||
type ScalewayImageDefinition struct {
|
||||
SnapshotIDentifier string `json:"root_volume"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Organization string `json:"organization"`
|
||||
Arch string `json:"arch"`
|
||||
DefaultBootscript *string `json:"default_bootscript,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayRoleDefinition represents a Scaleway Token UserId Role
|
||||
type ScalewayRoleDefinition struct {
|
||||
Organization ScalewayOrganizationDefinition `json:"organization,omitempty"`
|
||||
Role string `json:"role,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayTokenDefinition represents a Scaleway Token
|
||||
type ScalewayTokenDefinition struct {
|
||||
UserID string `json:"user_id"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Roles ScalewayRoleDefinition `json:"roles"`
|
||||
Expires string `json:"expires"`
|
||||
InheritsUsersPerms bool `json:"inherits_user_perms"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// ScalewayTokensDefinition represents a Scaleway Tokens
|
||||
type ScalewayTokensDefinition struct {
|
||||
Token ScalewayTokenDefinition `json:"token"`
|
||||
}
|
||||
|
||||
// ScalewayGetTokens represents a list of Scaleway Tokens
|
||||
type ScalewayGetTokens struct {
|
||||
Tokens []ScalewayTokenDefinition `json:"tokens"`
|
||||
}
|
||||
|
||||
// ScalewayContainerData represents a Scaleway container data (S3)
|
||||
type ScalewayContainerData struct {
|
||||
LastModified string `json:"last_modified"`
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
}
|
||||
|
||||
// ScalewayGetContainerDatas represents a list of Scaleway containers data (S3)
|
||||
type ScalewayGetContainerDatas struct {
|
||||
Container []ScalewayContainerData `json:"container"`
|
||||
}
|
||||
|
||||
// ScalewayContainer represents a Scaleway container (S3)
|
||||
type ScalewayContainer struct {
|
||||
ScalewayOrganizationDefinition `json:"organization"`
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
}
|
||||
|
||||
// ScalewayGetContainers represents a list of Scaleway containers (S3)
|
||||
type ScalewayGetContainers struct {
|
||||
Containers []ScalewayContainer `json:"containers"`
|
||||
}
|
||||
|
||||
// ScalewayConnectResponse represents the answer from POST /tokens
|
||||
type ScalewayConnectResponse struct {
|
||||
Token ScalewayTokenDefinition `json:"token"`
|
||||
}
|
||||
|
||||
// ScalewayConnect represents the data to connect
|
||||
type ScalewayConnect struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
Description string `json:"description"`
|
||||
Expires bool `json:"expires"`
|
||||
}
|
||||
|
||||
// ScalewayConnectInterface is the interface implemented by ScalewayConnect,
|
||||
// ScalewayConnectByOTP and ScalewayConnectByBackupCode
|
||||
type ScalewayConnectInterface interface {
|
||||
GetPassword() string
|
||||
}
|
||||
|
||||
func (s *ScalewayConnect) GetPassword() string {
|
||||
return s.Password
|
||||
}
|
||||
|
||||
type ScalewayConnectByOTP struct {
|
||||
ScalewayConnect
|
||||
TwoFAToken string `json:"2FA_token"`
|
||||
}
|
||||
|
||||
type ScalewayConnectByBackupCode struct {
|
||||
ScalewayConnect
|
||||
TwoFABackupCode string `json:"2FA_backup_code"`
|
||||
}
|
||||
|
||||
// ScalewayOrganizationDefinition represents a Scaleway Organization
|
||||
type ScalewayOrganizationDefinition struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Users []ScalewayUserDefinition `json:"users"`
|
||||
}
|
||||
|
||||
// ScalewayOrganizationsDefinition represents a Scaleway Organizations
|
||||
type ScalewayOrganizationsDefinition struct {
|
||||
Organizations []ScalewayOrganizationDefinition `json:"organizations"`
|
||||
}
|
||||
|
||||
// ScalewayUserDefinition represents a Scaleway User
|
||||
type ScalewayUserDefinition struct {
|
||||
Email string `json:"email"`
|
||||
Firstname string `json:"firstname"`
|
||||
Fullname string `json:"fullname"`
|
||||
ID string `json:"id"`
|
||||
Lastname string `json:"lastname"`
|
||||
Organizations []ScalewayOrganizationDefinition `json:"organizations"`
|
||||
Roles []ScalewayRoleDefinition `json:"roles"`
|
||||
SSHPublicKeys []ScalewayKeyDefinition `json:"ssh_public_keys"`
|
||||
}
|
||||
|
||||
// ScalewayUsersDefinition represents the response of a GET /user
|
||||
type ScalewayUsersDefinition struct {
|
||||
User ScalewayUserDefinition `json:"user"`
|
||||
}
|
||||
|
||||
// ScalewayKeyDefinition represents a key
|
||||
type ScalewayKeyDefinition struct {
|
||||
Key string `json:"key"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
}
|
||||
|
||||
// ScalewayUserPatchSSHKeyDefinition represents a User Patch
|
||||
type ScalewayUserPatchSSHKeyDefinition struct {
|
||||
SSHPublicKeys []ScalewayKeyDefinition `json:"ssh_public_keys"`
|
||||
}
|
||||
|
||||
// ScalewayDashboardResp represents a dashboard received from the API
|
||||
type ScalewayDashboardResp struct {
|
||||
Dashboard ScalewayDashboard
|
||||
}
|
||||
|
||||
// ScalewayDashboard represents a dashboard
|
||||
type ScalewayDashboard struct {
|
||||
VolumesCount int `json:"volumes_count"`
|
||||
RunningServersCount int `json:"running_servers_count"`
|
||||
ImagesCount int `json:"images_count"`
|
||||
SnapshotsCount int `json:"snapshots_count"`
|
||||
ServersCount int `json:"servers_count"`
|
||||
IPsCount int `json:"ips_count"`
|
||||
}
|
||||
|
||||
// ScalewayPermissions represents the response of GET /permissions
|
||||
type ScalewayPermissions map[string]ScalewayPermCategory
|
||||
|
||||
// ScalewayPermCategory represents ScalewayPermissions's fields
|
||||
type ScalewayPermCategory map[string][]string
|
||||
|
||||
// ScalewayPermissionDefinition represents the permissions
|
||||
type ScalewayPermissionDefinition struct {
|
||||
Permissions ScalewayPermissions `json:"permissions"`
|
||||
}
|
||||
|
||||
// ScalewayUserdatas represents the response of a GET /user_data
|
||||
type ScalewayUserdatas struct {
|
||||
UserData []string `json:"user_data"`
|
||||
}
|
||||
|
||||
// ScalewayQuota represents a map of quota (name, value)
|
||||
type ScalewayQuota map[string]int
|
||||
|
||||
// ScalewayGetQuotas represents the response of GET /organizations/{orga_id}/quotas
|
||||
type ScalewayGetQuotas struct {
|
||||
Quotas ScalewayQuota `json:"quotas"`
|
||||
}
|
||||
|
||||
// ScalewayUserdata represents []byte
|
||||
type ScalewayUserdata []byte
|
||||
|
||||
// FuncMap used for json inspection
|
||||
var FuncMap = template.FuncMap{
|
||||
"json": func(v interface{}) string {
|
||||
a, _ := json.Marshal(v)
|
||||
return string(a)
|
||||
},
|
||||
}
|
||||
|
||||
// MarketLocalImageDefinition represents localImage of marketplace version
|
||||
type MarketLocalImageDefinition struct {
|
||||
Arch string `json:"arch"`
|
||||
ID string `json:"id"`
|
||||
Zone string `json:"zone"`
|
||||
}
|
||||
|
||||
// MarketLocalImages represents an array of local images
|
||||
type MarketLocalImages struct {
|
||||
LocalImages []MarketLocalImageDefinition `json:"local_images"`
|
||||
}
|
||||
|
||||
// MarketLocalImage represents local image
|
||||
type MarketLocalImage struct {
|
||||
LocalImages MarketLocalImageDefinition `json:"local_image"`
|
||||
}
|
||||
|
||||
// MarketVersionDefinition represents version of marketplace image
|
||||
type MarketVersionDefinition struct {
|
||||
CreationDate string `json:"creation_date"`
|
||||
ID string `json:"id"`
|
||||
Image struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
} `json:"image"`
|
||||
ModificationDate string `json:"modification_date"`
|
||||
Name string `json:"name"`
|
||||
MarketLocalImages
|
||||
}
|
||||
|
||||
// MarketVersions represents an array of marketplace image versions
|
||||
type MarketVersions struct {
|
||||
Versions []MarketVersionDefinition `json:"versions"`
|
||||
}
|
||||
|
||||
// MarketVersion represents version of marketplace image
|
||||
type MarketVersion struct {
|
||||
Version MarketVersionDefinition `json:"version"`
|
||||
}
|
||||
|
||||
// MarketImage represents MarketPlace image
|
||||
type MarketImage struct {
|
||||
Categories []string `json:"categories"`
|
||||
CreationDate string `json:"creation_date"`
|
||||
CurrentPublicVersion string `json:"current_public_version"`
|
||||
Description string `json:"description"`
|
||||
ID string `json:"id"`
|
||||
Logo string `json:"logo"`
|
||||
ModificationDate string `json:"modification_date"`
|
||||
Name string `json:"name"`
|
||||
Organization struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
} `json:"organization"`
|
||||
Public bool `json:"-"`
|
||||
MarketVersions
|
||||
}
|
||||
|
||||
// MarketImages represents MarketPlace images
|
||||
type MarketImages struct {
|
||||
Images []MarketImage `json:"images"`
|
||||
}
|
||||
|
||||
// ScalewaySortServers represents a wrapper to sort by CreationDate the servers
|
||||
type ScalewaySortServers []ScalewayServer
|
||||
|
||||
func (s ScalewaySortServers) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s ScalewaySortServers) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s ScalewaySortServers) Less(i, j int) bool {
|
||||
date1, _ := time.Parse("2006-01-02T15:04:05.000000+00:00", s[i].CreationDate)
|
||||
date2, _ := time.Parse("2006-01-02T15:04:05.000000+00:00", s[j].CreationDate)
|
||||
return date2.Before(date1)
|
||||
}
|
||||
|
||||
func (s *ScalewayUserdata) String() string {
|
||||
return string(*s)
|
||||
}
|
191
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/LICENSE
generated
vendored
Normal file
191
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/LICENSE
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2019 Scaleway.
|
||||
|
||||
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
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
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.
|
81
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/README.md
generated
vendored
Normal file
81
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/README.md
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
<p align="center"><img height="125" src="docs/static_files/scaleway-logo.png" /></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://godoc.org/github.com/scaleway/scaleway-sdk-go"><img src="https://godoc.org/github.com/scaleway/scaleway-sdk-go?status.svg" alt="GoDoc"/></a>
|
||||
<a href="https://circleci.com/gh/scaleway/scaleway-sdk-go"><img src="https://circleci.com/gh/scaleway/scaleway-sdk-go.svg?style=shield" alt="CircleCI" /></a>
|
||||
<a href="https://goreportcard.com/report/github.com/scaleway/scaleway-sdk-go"><img src="https://goreportcard.com/badge/scaleway/scaleway-sdk-go" alt="GoReportCard" /></a>
|
||||
</p>
|
||||
|
||||
# Scaleway GO SDK
|
||||
|
||||
|
||||
**:warning: This is an early release, keep in mind that the API can break**
|
||||
|
||||
|
||||
Scaleway is a simple way to build, deploy and scale your infrastructure in the cloud.
|
||||
We help thousands of developers and businesses to run their infrastructures without any issue.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Godoc](https://godoc.org/github.com/scaleway/scaleway-sdk-go)
|
||||
- [Developers website](https://developers.scaleway.com) (API documentation)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/scaleway/scaleway-sdk-go
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
|
||||
"github.com/scaleway/scaleway-sdk-go/scw"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// Create a Scaleway client
|
||||
client, err := scw.NewClient(
|
||||
// Get your credentials at https://console.scaleway.com/account/credentials
|
||||
scw.WithDefaultProjectID("ORGANISATION_ID"),
|
||||
scw.WithAuth("ACCESS_KEY", "SECRET_KEY"),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create SDK objects for Scaleway Instance product
|
||||
instanceApi := instance.NewAPI(client)
|
||||
|
||||
// Call the ListServers method on the Instance SDK
|
||||
response, err := instanceApi.ListServers(&instance.ListServersRequest{
|
||||
Zone: utils.ZoneFrPar1,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Do something with the response...
|
||||
for _, server := range response.Servers {
|
||||
fmt.Println("Server", server.ID, server.Name)
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
This repository is at its early stage and is still in active development.
|
||||
If you are looking for a way to contribute please read [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
|
||||
## Reach us
|
||||
|
||||
We love feedback.
|
||||
Feel free to reach us on [Scaleway Slack community](https://slack.scaleway.com/), we are waiting for you on [#opensource](https://scaleway-community.slack.com/app_redirect?channel=opensource).
|
278
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/instance_metadata_sdk.go
generated
vendored
Normal file
278
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/instance_metadata_sdk.go
generated
vendored
Normal file
@ -0,0 +1,278 @@
|
||||
package instance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
metadataURL = "http://169.254.42.42"
|
||||
metadataRetryBindPort = 200
|
||||
)
|
||||
|
||||
// MetadataAPI metadata API
|
||||
type MetadataAPI struct {
|
||||
}
|
||||
|
||||
// NewMetadataAPI returns a MetadataAPI object from a Scaleway client.
|
||||
func NewMetadataAPI() *MetadataAPI {
|
||||
return &MetadataAPI{}
|
||||
}
|
||||
|
||||
// GetMetadata returns the metadata available from the server
|
||||
func (*MetadataAPI) GetMetadata() (m *Metadata, err error) {
|
||||
resp, err := http.Get(metadataURL + "/conf?format=json")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error getting metadataURL")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
metadata := &Metadata{}
|
||||
err = json.NewDecoder(resp.Body).Decode(metadata)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error decoding metadata")
|
||||
}
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
// Metadata represents the struct return by the metadata API
|
||||
type Metadata struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
Organization string `json:"organization,omitempty"`
|
||||
CommercialType string `json:"commercial_type,omitempty"`
|
||||
PublicIP struct {
|
||||
Dynamic bool `json:"dynamic,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Address string `json:"address,omitempty"`
|
||||
} `json:"public_ip,omitempty"`
|
||||
PrivateIP string `json:"private_ip,omitempty"`
|
||||
IPv6 struct {
|
||||
Netmask string `json:"netmask,omitempty"`
|
||||
Gateway string `json:"gateway,omitempty"`
|
||||
Address string `json:"address,omitempty"`
|
||||
} `json:"ipv6,omitempty"`
|
||||
Location struct {
|
||||
PlatformID string `json:"platform_id,omitempty"`
|
||||
HypervisorID string `json:"hypervisor_id,omitempty"`
|
||||
NodeID string `json:"node_id,omitempty"`
|
||||
ClusterID string `json:"cluster_id,omitempty"`
|
||||
ZoneID string `json:"zone_id,omitempty"`
|
||||
} `json:"location,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
StateDetail string `json:"state_detail,omitempty"`
|
||||
SSHPublicKeys []struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
IP string `json:"ip,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
UserAgent struct {
|
||||
Platform string `json:"platform,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
String string `json:"string,omitempty"`
|
||||
Browser string `json:"browser,omitempty"`
|
||||
} `json:"user_agent,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
Port int `json:"port,omitempty"`
|
||||
} `json:"ssh_public_keys,omitempty"`
|
||||
Timezone string `json:"timezone,omitempty"`
|
||||
Bootscript struct {
|
||||
Kernel string `json:"kernel,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Default bool `json:"default,omitempty"`
|
||||
Dtb string `json:"dtb,omitempty"`
|
||||
Public bool `json:"publc,omitempty"`
|
||||
Initrd string `json:"initrd,omitempty"`
|
||||
Bootcmdargs string `json:"bootcmdargs,omitempty"`
|
||||
Architecture string `json:"architecture,omitempty"`
|
||||
Organization string `json:"organization,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
} `json:"bootscript,omitempty"`
|
||||
Volumes map[string]struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
ModificationDate string `json:"modification_date,omitempty"`
|
||||
ExportURI string `json:"export_uri,omitempty"`
|
||||
VolumeType string `json:"volume_type,omitempty"`
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
State string `json:"state,omitempty"`
|
||||
Organization string `json:"organization,omitempty"`
|
||||
Server struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
} `json:"server,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Size int `json:"size,omitempty"`
|
||||
}
|
||||
}
|
||||
|
||||
// ListUserdata returns the metadata available from the server
|
||||
func (*MetadataAPI) ListUserdata() (res *Userdata, err error) {
|
||||
retries := 0
|
||||
for retries <= metadataRetryBindPort {
|
||||
port := rand.Intn(1024)
|
||||
localTCPAddr, err := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(port))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error resolving tcp address")
|
||||
}
|
||||
|
||||
userdataClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
LocalAddr: localTCPAddr,
|
||||
DualStack: false,
|
||||
FallbackDelay: time.Second * -1,
|
||||
}).DialContext,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := userdataClient.Get(metadataURL + "/user_data?format=json")
|
||||
if err != nil {
|
||||
retries++ // retry with a different source port
|
||||
continue
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
userdata := &Userdata{}
|
||||
err = json.NewDecoder(resp.Body).Decode(userdata)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error decoding userdata")
|
||||
}
|
||||
return userdata, nil
|
||||
}
|
||||
return nil, errors.New("too many bind port retries for ListUserdata")
|
||||
}
|
||||
|
||||
// GetUserdata returns the value for the given metadata key
|
||||
func (*MetadataAPI) GetUserdata(key string) ([]byte, error) {
|
||||
if key == "" {
|
||||
return make([]byte, 0), errors.New("key must not be empty in GetUserdata")
|
||||
}
|
||||
|
||||
retries := 0
|
||||
for retries <= metadataRetryBindPort {
|
||||
port := rand.Intn(1024)
|
||||
localTCPAddr, err := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(port))
|
||||
if err != nil {
|
||||
return make([]byte, 0), errors.Wrap(err, "error resolving tcp address")
|
||||
}
|
||||
|
||||
userdataClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
LocalAddr: localTCPAddr,
|
||||
DualStack: false,
|
||||
FallbackDelay: time.Second * -1,
|
||||
}).DialContext,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := userdataClient.Get(metadataURL + "/user_data/" + key)
|
||||
if err != nil {
|
||||
retries++ // retry with a different source port
|
||||
continue
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return make([]byte, 0), errors.Wrap(err, "error reading userdata body")
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
return make([]byte, 0), errors.New("too may bind port retries for GetUserdata")
|
||||
}
|
||||
|
||||
// SetUserdata sets the userdata key with the given value
|
||||
func (*MetadataAPI) SetUserdata(key string, value []byte) error {
|
||||
if key == "" {
|
||||
return errors.New("key must not be empty in SetUserdata")
|
||||
}
|
||||
|
||||
retries := 0
|
||||
for retries <= metadataRetryBindPort {
|
||||
port := rand.Intn(1024)
|
||||
localTCPAddr, err := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(port))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error resolving tcp address")
|
||||
}
|
||||
|
||||
userdataClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
LocalAddr: localTCPAddr,
|
||||
DualStack: false,
|
||||
FallbackDelay: time.Second * -1,
|
||||
}).DialContext,
|
||||
},
|
||||
}
|
||||
request, err := http.NewRequest("PATCH", metadataURL+"/user_data/"+key, bytes.NewBuffer(value))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating patch userdata request")
|
||||
}
|
||||
request.Header.Set("Content-Type", "text/plain")
|
||||
_, err = userdataClient.Do(request)
|
||||
if err != nil {
|
||||
retries++ // retry with a different source port
|
||||
continue
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
return errors.New("too may bind port retries for SetUserdata")
|
||||
}
|
||||
|
||||
// DeleteUserdata deletes the userdata key and the associated value
|
||||
func (*MetadataAPI) DeleteUserdata(key string) error {
|
||||
if key == "" {
|
||||
return errors.New("key must not be empty in DeleteUserdata")
|
||||
}
|
||||
|
||||
retries := 0
|
||||
for retries <= metadataRetryBindPort {
|
||||
port := rand.Intn(1024)
|
||||
localTCPAddr, err := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(port))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error resolving tcp address")
|
||||
}
|
||||
|
||||
userdataClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
LocalAddr: localTCPAddr,
|
||||
DualStack: false,
|
||||
FallbackDelay: time.Second * -1,
|
||||
}).DialContext,
|
||||
},
|
||||
}
|
||||
request, err := http.NewRequest("DELETE", metadataURL+"/user_data/"+key, bytes.NewBuffer([]byte("")))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating delete userdata request")
|
||||
}
|
||||
_, err = userdataClient.Do(request)
|
||||
if err != nil {
|
||||
retries++ // retry with a different source port
|
||||
continue
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
return errors.New("too may bind port retries for DeleteUserdata")
|
||||
}
|
||||
|
||||
// Userdata represents the user data
|
||||
type Userdata struct {
|
||||
UserData []string `json:"user_data,omitempty"`
|
||||
}
|
3540
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/instance_sdk.go
generated
vendored
Normal file
3540
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/instance_sdk.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
255
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/instance_utils.go
generated
vendored
Normal file
255
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/instance_utils.go
generated
vendored
Normal file
@ -0,0 +1,255 @@
|
||||
package instance
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/scw"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
)
|
||||
|
||||
// AttachIPRequest contains the parameters to attach an IP to a server
|
||||
type AttachIPRequest struct {
|
||||
Zone utils.Zone `json:"-"`
|
||||
IPID string `json:"-"`
|
||||
ServerID string `json:"server_id"`
|
||||
}
|
||||
|
||||
// AttachIPResponse contains the updated IP after attaching
|
||||
type AttachIPResponse struct {
|
||||
IP *IP
|
||||
}
|
||||
|
||||
// AttachIP attaches an IP to a server.
|
||||
func (s *API) AttachIP(req *AttachIPRequest, opts ...scw.RequestOption) (*AttachIPResponse, error) {
|
||||
var ptrServerID = &req.ServerID
|
||||
ipResponse, err := s.updateIP(&updateIPRequest{
|
||||
Zone: req.Zone,
|
||||
IPID: req.IPID,
|
||||
Server: &ptrServerID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &AttachIPResponse{IP: ipResponse.IP}, nil
|
||||
}
|
||||
|
||||
// DetachIPRequest contains the parameters to detach an IP from a server
|
||||
type DetachIPRequest struct {
|
||||
Zone utils.Zone `json:"-"`
|
||||
IPID string `json:"-"`
|
||||
}
|
||||
|
||||
// DetachIPResponse contains the updated IP after detaching
|
||||
type DetachIPResponse struct {
|
||||
IP *IP
|
||||
}
|
||||
|
||||
// DetachIP detaches an IP from a server.
|
||||
func (s *API) DetachIP(req *DetachIPRequest, opts ...scw.RequestOption) (*DetachIPResponse, error) {
|
||||
var ptrServerID *string
|
||||
ipResponse, err := s.updateIP(&updateIPRequest{
|
||||
Zone: req.Zone,
|
||||
IPID: req.IPID,
|
||||
Server: &ptrServerID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DetachIPResponse{IP: ipResponse.IP}, nil
|
||||
}
|
||||
|
||||
// UpdateIPRequest contains the parameters to update an IP
|
||||
// if Reverse is an empty string, the reverse will be removed
|
||||
type UpdateIPRequest struct {
|
||||
Zone utils.Zone `json:"-"`
|
||||
IPID string `json:"-"`
|
||||
Reverse *string `json:"reverse"`
|
||||
}
|
||||
|
||||
// UpdateIP updates an IP
|
||||
func (s *API) UpdateIP(req *UpdateIPRequest, opts ...scw.RequestOption) (*UpdateIPResponse, error) {
|
||||
var reverse **string
|
||||
if req.Reverse != nil {
|
||||
if *req.Reverse == "" {
|
||||
req.Reverse = nil
|
||||
}
|
||||
reverse = &req.Reverse
|
||||
}
|
||||
ipResponse, err := s.updateIP(&updateIPRequest{
|
||||
Zone: req.Zone,
|
||||
IPID: req.IPID,
|
||||
Reverse: reverse,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &UpdateIPResponse{IP: ipResponse.IP}, nil
|
||||
}
|
||||
|
||||
// AttachVolumeRequest contains the parameters to attach a volume to a server
|
||||
type AttachVolumeRequest struct {
|
||||
Zone utils.Zone `json:"-"`
|
||||
ServerID string `json:"-"`
|
||||
VolumeID string `json:"-"`
|
||||
}
|
||||
|
||||
// AttachVolumeResponse contains the updated server after attaching a volume
|
||||
type AttachVolumeResponse struct {
|
||||
Server *Server `json:"-"`
|
||||
}
|
||||
|
||||
// volumesToVolumeTemplates converts a map of *Volume to a map of *VolumeTemplate
|
||||
// so it can be used in a UpdateServer request
|
||||
func volumesToVolumeTemplates(volumes map[string]*Volume) map[string]*VolumeTemplate {
|
||||
volumeTemplates := map[string]*VolumeTemplate{}
|
||||
for key, volume := range volumes {
|
||||
volumeTemplates[key] = &VolumeTemplate{ID: volume.ID, Name: volume.Name}
|
||||
}
|
||||
return volumeTemplates
|
||||
}
|
||||
|
||||
// AttachVolume attaches a volume to a server
|
||||
func (s *API) AttachVolume(req *AttachVolumeRequest, opts ...scw.RequestOption) (*AttachVolumeResponse, error) {
|
||||
// get server with volumes
|
||||
getServerResponse, err := s.GetServer(&GetServerRequest{
|
||||
Zone: req.Zone,
|
||||
ServerID: req.ServerID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
volumes := getServerResponse.Server.Volumes
|
||||
|
||||
newVolumes := volumesToVolumeTemplates(volumes)
|
||||
|
||||
// add volume to volumes list
|
||||
key := fmt.Sprintf("%d", len(volumes))
|
||||
newVolumes[key] = &VolumeTemplate{
|
||||
ID: req.VolumeID,
|
||||
// name is ignored on this PATCH
|
||||
Name: req.VolumeID,
|
||||
}
|
||||
|
||||
// update server
|
||||
updateServerResponse, err := s.UpdateServer(&UpdateServerRequest{
|
||||
Zone: req.Zone,
|
||||
ServerID: req.ServerID,
|
||||
Volumes: &newVolumes,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &AttachVolumeResponse{Server: updateServerResponse.Server}, nil
|
||||
}
|
||||
|
||||
// DetachVolumeRequest contains the parameters to detach a volume from a server
|
||||
type DetachVolumeRequest struct {
|
||||
Zone utils.Zone `json:"-"`
|
||||
VolumeID string `json:"-"`
|
||||
}
|
||||
|
||||
// DetachVolumeResponse contains the updated server after detaching a volume
|
||||
type DetachVolumeResponse struct {
|
||||
Server *Server `json:"-"`
|
||||
}
|
||||
|
||||
// DetachVolume detaches a volume from a server
|
||||
func (s *API) DetachVolume(req *DetachVolumeRequest, opts ...scw.RequestOption) (*DetachVolumeResponse, error) {
|
||||
// get volume
|
||||
getVolumeResponse, err := s.GetVolume(&GetVolumeRequest{
|
||||
Zone: req.Zone,
|
||||
VolumeID: req.VolumeID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if getVolumeResponse.Volume == nil {
|
||||
return nil, fmt.Errorf("expected volume to have value in response")
|
||||
}
|
||||
if getVolumeResponse.Volume.Server == nil {
|
||||
return nil, fmt.Errorf("server should be attached to a server")
|
||||
}
|
||||
serverID := getVolumeResponse.Volume.Server.ID
|
||||
|
||||
// get server with volumes
|
||||
getServerResponse, err := s.GetServer(&GetServerRequest{
|
||||
Zone: req.Zone,
|
||||
ServerID: serverID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
volumes := getServerResponse.Server.Volumes
|
||||
// remove volume from volumes list
|
||||
for key, volume := range volumes {
|
||||
if volume.ID == req.VolumeID {
|
||||
delete(volumes, key)
|
||||
}
|
||||
}
|
||||
|
||||
newVolumes := volumesToVolumeTemplates(volumes)
|
||||
|
||||
// update server
|
||||
updateServerResponse, err := s.UpdateServer(&UpdateServerRequest{
|
||||
Zone: req.Zone,
|
||||
ServerID: serverID,
|
||||
Volumes: &newVolumes,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DetachVolumeResponse{Server: updateServerResponse.Server}, nil
|
||||
}
|
||||
|
||||
// UnsafeSetTotalCount should not be used
|
||||
// Internal usage only
|
||||
func (r *ListServersResponse) UnsafeSetTotalCount(totalCount int) {
|
||||
r.TotalCount = uint32(totalCount)
|
||||
}
|
||||
|
||||
// UnsafeSetTotalCount should not be used
|
||||
// Internal usage only
|
||||
func (r *ListBootscriptsResponse) UnsafeSetTotalCount(totalCount int) {
|
||||
r.TotalCount = uint32(totalCount)
|
||||
}
|
||||
|
||||
// UnsafeSetTotalCount should not be used
|
||||
// Internal usage only
|
||||
func (r *ListIpsResponse) UnsafeSetTotalCount(totalCount int) {
|
||||
r.TotalCount = uint32(totalCount)
|
||||
}
|
||||
|
||||
// UnsafeSetTotalCount should not be used
|
||||
// Internal usage only
|
||||
func (r *ListSecurityGroupRulesResponse) UnsafeSetTotalCount(totalCount int) {
|
||||
r.TotalCount = uint32(totalCount)
|
||||
}
|
||||
|
||||
// UnsafeSetTotalCount should not be used
|
||||
// Internal usage only
|
||||
func (r *ListSecurityGroupsResponse) UnsafeSetTotalCount(totalCount int) {
|
||||
r.TotalCount = uint32(totalCount)
|
||||
}
|
||||
|
||||
// UnsafeSetTotalCount should not be used
|
||||
// Internal usage only
|
||||
func (r *ListServersTypesResponse) UnsafeSetTotalCount(totalCount int) {
|
||||
r.TotalCount = uint32(totalCount)
|
||||
}
|
||||
|
||||
// UnsafeSetTotalCount should not be used
|
||||
// Internal usage only
|
||||
func (r *ListSnapshotsResponse) UnsafeSetTotalCount(totalCount int) {
|
||||
r.TotalCount = uint32(totalCount)
|
||||
}
|
||||
|
||||
// UnsafeSetTotalCount should not be used
|
||||
// Internal usage only
|
||||
func (r *ListVolumesResponse) UnsafeSetTotalCount(totalCount int) {
|
||||
r.TotalCount = uint32(totalCount)
|
||||
}
|
53
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/server_utils.go
generated
vendored
Normal file
53
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/instance/v1/server_utils.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
package instance
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/async"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
)
|
||||
|
||||
// WaitForServerRequest is used by WaitForServer method
|
||||
type WaitForServerRequest struct {
|
||||
ServerID string
|
||||
Zone utils.Zone
|
||||
|
||||
// Timeout: maximum time to wait before (default: 5 minutes)
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// WaitForServer wait for the server to be in a "terminal state" before returning.
|
||||
// This function can be used to wait for a server to be started for example.
|
||||
func (s *API) WaitForServer(req *WaitForServerRequest) (*Server, error) {
|
||||
|
||||
if req.Timeout == 0 {
|
||||
req.Timeout = 5 * time.Minute
|
||||
}
|
||||
|
||||
terminalStatus := map[ServerState]struct{}{
|
||||
ServerStateStopped: {},
|
||||
ServerStateStoppedInPlace: {},
|
||||
ServerStateLocked: {},
|
||||
ServerStateRunning: {},
|
||||
}
|
||||
|
||||
server, err := async.WaitSync(&async.WaitSyncConfig{
|
||||
Get: func() (interface{}, error, bool) {
|
||||
res, err := s.GetServer(&GetServerRequest{
|
||||
ServerID: req.ServerID,
|
||||
Zone: req.Zone,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err, false
|
||||
}
|
||||
_, isTerminal := terminalStatus[res.Server.State]
|
||||
|
||||
return res.Server, err, isTerminal
|
||||
},
|
||||
Timeout: req.Timeout,
|
||||
IntervalStrategy: async.LinearIntervalStrategy(5 * time.Second),
|
||||
})
|
||||
|
||||
return server.(*Server), err
|
||||
}
|
265
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/marketplace/v1/marketplace_sdk.go
generated
vendored
Normal file
265
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/marketplace/v1/marketplace_sdk.go
generated
vendored
Normal file
@ -0,0 +1,265 @@
|
||||
// This file was automatically generated. DO NOT EDIT.
|
||||
// If you have any remark or suggestion do not hesitate to open an issue.
|
||||
|
||||
package marketplace
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/errors"
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/marshaler"
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/parameter"
|
||||
"github.com/scaleway/scaleway-sdk-go/scw"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
)
|
||||
|
||||
// always import dependencies
|
||||
var (
|
||||
_ fmt.Stringer
|
||||
_ json.Unmarshaler
|
||||
_ url.URL
|
||||
_ net.IP
|
||||
_ http.Header
|
||||
_ bytes.Reader
|
||||
_ time.Time
|
||||
|
||||
_ scw.ScalewayRequest
|
||||
_ marshaler.Duration
|
||||
_ utils.File
|
||||
_ = parameter.AddToQuery
|
||||
)
|
||||
|
||||
// API marketplace API
|
||||
type API struct {
|
||||
client *scw.Client
|
||||
}
|
||||
|
||||
// NewAPI returns a API object from a Scaleway client.
|
||||
func NewAPI(client *scw.Client) *API {
|
||||
return &API{
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
type GetImageResponse struct {
|
||||
Image *Image `json:"image,omitempty"`
|
||||
}
|
||||
|
||||
type GetServiceInfoResponse struct {
|
||||
API string `json:"api,omitempty"`
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
type GetVersionResponse struct {
|
||||
Version *Version `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
Logo string `json:"logo,omitempty"`
|
||||
|
||||
Categories []string `json:"categories,omitempty"`
|
||||
|
||||
Organization *Organization `json:"organization,omitempty"`
|
||||
|
||||
ValidUntil time.Time `json:"valid_until,omitempty"`
|
||||
|
||||
CreationDate time.Time `json:"creation_date,omitempty"`
|
||||
|
||||
ModificationDate time.Time `json:"modification_date,omitempty"`
|
||||
|
||||
Versions []*Version `json:"versions,omitempty"`
|
||||
|
||||
CurrentPublicVersion string `json:"current_public_version,omitempty"`
|
||||
}
|
||||
|
||||
type ListImagesResponse struct {
|
||||
Images []*Image `json:"images,omitempty"`
|
||||
}
|
||||
|
||||
type ListVersionsResponse struct {
|
||||
Versions []*Version `json:"versions,omitempty"`
|
||||
}
|
||||
|
||||
type LocalImage struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
|
||||
Arch string `json:"arch,omitempty"`
|
||||
|
||||
Zone utils.Zone `json:"zone,omitempty"`
|
||||
|
||||
CompatibleCommercialTypes []string `json:"compatible_commercial_types,omitempty"`
|
||||
}
|
||||
|
||||
type Organization struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type Version struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
CreationDate time.Time `json:"creation_date,omitempty"`
|
||||
|
||||
ModificationDate time.Time `json:"modification_date,omitempty"`
|
||||
|
||||
LocalImages []*LocalImage `json:"local_images,omitempty"`
|
||||
}
|
||||
|
||||
// Service API
|
||||
|
||||
type GetServiceInfoRequest struct {
|
||||
}
|
||||
|
||||
func (s *API) GetServiceInfo(req *GetServiceInfoRequest, opts ...scw.RequestOption) (*GetServiceInfoResponse, error) {
|
||||
var err error
|
||||
|
||||
scwReq := &scw.ScalewayRequest{
|
||||
Method: "GET",
|
||||
Path: "/marketplace/v1",
|
||||
Headers: http.Header{},
|
||||
}
|
||||
|
||||
var resp GetServiceInfoResponse
|
||||
|
||||
err = s.client.Do(scwReq, &resp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
type ListImagesRequest struct {
|
||||
PerPage *int32 `json:"-"`
|
||||
|
||||
Page *int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (s *API) ListImages(req *ListImagesRequest, opts ...scw.RequestOption) (*ListImagesResponse, error) {
|
||||
var err error
|
||||
|
||||
defaultPerPage, exist := s.client.GetDefaultPageSize()
|
||||
if (req.PerPage == nil || *req.PerPage == 0) && exist {
|
||||
req.PerPage = &defaultPerPage
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
parameter.AddToQuery(query, "per_page", req.PerPage)
|
||||
parameter.AddToQuery(query, "page", req.Page)
|
||||
|
||||
scwReq := &scw.ScalewayRequest{
|
||||
Method: "GET",
|
||||
Path: "/marketplace/v1/images",
|
||||
Query: query,
|
||||
Headers: http.Header{},
|
||||
}
|
||||
|
||||
var resp ListImagesResponse
|
||||
|
||||
err = s.client.Do(scwReq, &resp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
type GetImageRequest struct {
|
||||
ImageID string `json:"-"`
|
||||
}
|
||||
|
||||
func (s *API) GetImage(req *GetImageRequest, opts ...scw.RequestOption) (*GetImageResponse, error) {
|
||||
var err error
|
||||
|
||||
if fmt.Sprint(req.ImageID) == "" {
|
||||
return nil, errors.New("field ImageID cannot be empty in request")
|
||||
}
|
||||
|
||||
scwReq := &scw.ScalewayRequest{
|
||||
Method: "GET",
|
||||
Path: "/marketplace/v1/images/" + fmt.Sprint(req.ImageID) + "",
|
||||
Headers: http.Header{},
|
||||
}
|
||||
|
||||
var resp GetImageResponse
|
||||
|
||||
err = s.client.Do(scwReq, &resp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
type ListVersionsRequest struct {
|
||||
ImageID string `json:"-"`
|
||||
}
|
||||
|
||||
func (s *API) ListVersions(req *ListVersionsRequest, opts ...scw.RequestOption) (*ListVersionsResponse, error) {
|
||||
var err error
|
||||
|
||||
if fmt.Sprint(req.ImageID) == "" {
|
||||
return nil, errors.New("field ImageID cannot be empty in request")
|
||||
}
|
||||
|
||||
scwReq := &scw.ScalewayRequest{
|
||||
Method: "GET",
|
||||
Path: "/marketplace/v1/images/" + fmt.Sprint(req.ImageID) + "/versions",
|
||||
Headers: http.Header{},
|
||||
}
|
||||
|
||||
var resp ListVersionsResponse
|
||||
|
||||
err = s.client.Do(scwReq, &resp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
type GetVersionRequest struct {
|
||||
ImageID string `json:"-"`
|
||||
|
||||
VersionID string `json:"-"`
|
||||
}
|
||||
|
||||
func (s *API) GetVersion(req *GetVersionRequest, opts ...scw.RequestOption) (*GetVersionResponse, error) {
|
||||
var err error
|
||||
|
||||
if fmt.Sprint(req.ImageID) == "" {
|
||||
return nil, errors.New("field ImageID cannot be empty in request")
|
||||
}
|
||||
|
||||
if fmt.Sprint(req.VersionID) == "" {
|
||||
return nil, errors.New("field VersionID cannot be empty in request")
|
||||
}
|
||||
|
||||
scwReq := &scw.ScalewayRequest{
|
||||
Method: "GET",
|
||||
Path: "/marketplace/v1/images/" + fmt.Sprint(req.ImageID) + "/versions/" + fmt.Sprint(req.VersionID) + "",
|
||||
Headers: http.Header{},
|
||||
}
|
||||
|
||||
var resp GetVersionResponse
|
||||
|
||||
err = s.client.Do(scwReq, &resp, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
81
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/marketplace/v1/marketplace_utils.go
generated
vendored
Normal file
81
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/api/marketplace/v1/marketplace_utils.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
package marketplace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
)
|
||||
|
||||
// getLocalImage returns the correct local version of an image matching
|
||||
// the current zone and the compatible commercial type
|
||||
func (version *Version) getLocalImage(zone utils.Zone, commercialType string) (*LocalImage, error) {
|
||||
|
||||
for _, localImage := range version.LocalImages {
|
||||
|
||||
// Check if in correct zone
|
||||
if localImage.Zone != zone {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if compatible with wanted commercial type
|
||||
for _, compatibleCommercialType := range localImage.CompatibleCommercialTypes {
|
||||
if compatibleCommercialType == commercialType {
|
||||
return localImage, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("couldn't find compatible local image for this image version (%s)", version.ID)
|
||||
|
||||
}
|
||||
|
||||
// getLatestVersion returns the current/latests version on an image,
|
||||
// or an error in case the image doesn't have a public version.
|
||||
func (image *Image) getLatestVersion() (*Version, error) {
|
||||
|
||||
for _, version := range image.Versions {
|
||||
if version.ID == image.CurrentPublicVersion {
|
||||
return version, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("latest version could not be found for image %s", image.Name)
|
||||
}
|
||||
|
||||
// FindLocalImageIDByName search for an image with the given name (exact match) in the given region
|
||||
// it returns the latest version of this specific image.
|
||||
func (s *API) FindLocalImageIDByName(imageName string, zone utils.Zone, commercialType string) (string, error) {
|
||||
|
||||
listImageRequest := &ListImagesRequest{}
|
||||
listImageResponse, err := s.ListImages(listImageRequest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// TODO: handle pagination
|
||||
|
||||
images := listImageResponse.Images
|
||||
_ = images
|
||||
|
||||
for _, image := range images {
|
||||
|
||||
// Match name of the image
|
||||
if image.Name == imageName {
|
||||
|
||||
latestVersion, err := image.getLatestVersion()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("couldn't find a matching image for the given name (%s), zone (%s) and commercial type (%s): %s", imageName, zone, commercialType, err)
|
||||
}
|
||||
|
||||
localImage, err := latestVersion.getLocalImage(zone, commercialType)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("couldn't find a matching image for the given name (%s), zone (%s) and commercial type (%s): %s", imageName, zone, commercialType, err)
|
||||
}
|
||||
|
||||
return localImage.ID, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("couldn't find a matching image for the given name (%s), zone (%s) and commercial type (%s)", imageName, zone, commercialType)
|
||||
}
|
8
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/go.mod
generated
vendored
Normal file
8
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/go.mod
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
module github.com/scaleway/scaleway-sdk-go
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/dnaeon/go-vcr v1.0.1
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
)
|
89
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/async/wait.go
generated
vendored
Normal file
89
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/async/wait.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
package async
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultInterval = time.Second
|
||||
defaultTimeout = time.Minute * 5
|
||||
)
|
||||
|
||||
type IntervalStrategy func() <-chan time.Time
|
||||
|
||||
// WaitSyncConfig defines the waiting options.
|
||||
type WaitSyncConfig struct {
|
||||
// This method will be called from another goroutine.
|
||||
Get func() (value interface{}, err error, isTerminal bool)
|
||||
IntervalStrategy IntervalStrategy
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// LinearIntervalStrategy defines a linear interval duration.
|
||||
func LinearIntervalStrategy(interval time.Duration) IntervalStrategy {
|
||||
return func() <-chan time.Time {
|
||||
return time.After(interval)
|
||||
}
|
||||
}
|
||||
|
||||
// FibonacciIntervalStrategy defines an interval duration who follow the Fibonacci sequence.
|
||||
func FibonacciIntervalStrategy(base time.Duration, factor float32) IntervalStrategy {
|
||||
var x, y float32 = 0, 1
|
||||
|
||||
return func() <-chan time.Time {
|
||||
x, y = y, x+(y*factor)
|
||||
return time.After(time.Duration(x) * base)
|
||||
}
|
||||
}
|
||||
|
||||
// WaitSync waits and returns when a given stop condition is true or if an error occurs.
|
||||
func WaitSync(config *WaitSyncConfig) (terminalValue interface{}, err error) {
|
||||
// initialize configuration
|
||||
if config.IntervalStrategy == nil {
|
||||
config.IntervalStrategy = LinearIntervalStrategy(defaultInterval)
|
||||
}
|
||||
if config.Timeout == 0 {
|
||||
config.Timeout = defaultTimeout
|
||||
}
|
||||
|
||||
resultValue := make(chan interface{})
|
||||
resultErr := make(chan error)
|
||||
timeout := make(chan bool)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
// get the payload
|
||||
value, err, stopCondition := config.Get()
|
||||
|
||||
// send the payload
|
||||
if err != nil {
|
||||
resultErr <- err
|
||||
return
|
||||
}
|
||||
if stopCondition {
|
||||
resultValue <- value
|
||||
return
|
||||
}
|
||||
|
||||
// waiting for an interval before next get() call or a timeout
|
||||
select {
|
||||
case <-timeout:
|
||||
return
|
||||
case <-config.IntervalStrategy():
|
||||
// sleep
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// waiting for a result or a timeout
|
||||
select {
|
||||
case val := <-resultValue:
|
||||
return val, nil
|
||||
case err := <-resultErr:
|
||||
return nil, err
|
||||
case <-time.After(config.Timeout):
|
||||
timeout <- true
|
||||
return nil, fmt.Errorf("timeout after %v", config.Timeout)
|
||||
}
|
||||
}
|
14
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/auth.go
generated
vendored
Normal file
14
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/auth.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package auth
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Auth implement methods required for authentication.
|
||||
// Valid authentication are currently a token or no auth.
|
||||
type Auth interface {
|
||||
// Headers returns headers that must be add to the http request
|
||||
Headers() http.Header
|
||||
|
||||
// AnonymizedHeaders returns an anonymised version of Headers()
|
||||
// This method could be use for logging purpose.
|
||||
AnonymizedHeaders() http.Header
|
||||
}
|
19
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/no_auth.go
generated
vendored
Normal file
19
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/no_auth.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
package auth
|
||||
|
||||
import "net/http"
|
||||
|
||||
type noAuth struct {
|
||||
}
|
||||
|
||||
// NewNoAuth return an auth with no authentication method
|
||||
func NewNoAuth() *noAuth {
|
||||
return &noAuth{}
|
||||
}
|
||||
|
||||
func (t *noAuth) Headers() http.Header {
|
||||
return http.Header{}
|
||||
}
|
||||
|
||||
func (t *noAuth) AnonymizedHeaders() http.Header {
|
||||
return http.Header{}
|
||||
}
|
42
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/token.go
generated
vendored
Normal file
42
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/auth/token.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
package auth
|
||||
|
||||
import "net/http"
|
||||
|
||||
type token struct {
|
||||
accessKey string
|
||||
secretKey string
|
||||
}
|
||||
|
||||
// XAuthTokenHeader is Scaleway standard auth header
|
||||
const XAuthTokenHeader = "X-Auth-Token"
|
||||
|
||||
// NewToken create a token authentication from an
|
||||
// access key and a secret key
|
||||
func NewToken(accessKey, secretKey string) *token {
|
||||
return &token{accessKey: accessKey, secretKey: secretKey}
|
||||
}
|
||||
|
||||
// Headers returns headers that must be add to the http request
|
||||
func (t *token) Headers() http.Header {
|
||||
headers := http.Header{}
|
||||
headers.Set(XAuthTokenHeader, t.secretKey)
|
||||
return headers
|
||||
}
|
||||
|
||||
// AnonymizedHeaders returns an anonymized version of Headers()
|
||||
// This method could be use for logging purpose.
|
||||
func (t *token) AnonymizedHeaders() http.Header {
|
||||
headers := http.Header{}
|
||||
var secret string
|
||||
|
||||
switch {
|
||||
case len(t.secretKey) == 0:
|
||||
secret = ""
|
||||
case len(t.secretKey) > 8:
|
||||
secret = t.secretKey[0:8] + "-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
default:
|
||||
secret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
}
|
||||
headers.Set(XAuthTokenHeader, secret)
|
||||
return headers
|
||||
}
|
41
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/errors/error.go
generated
vendored
Normal file
41
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/errors/error.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Error is a base error that implement scw.SdkError
|
||||
type Error struct {
|
||||
str string
|
||||
err error
|
||||
}
|
||||
|
||||
// Error implement standard xerror.Wrapper interface
|
||||
func (e *Error) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
// Error implement standard error interface
|
||||
func (e *Error) Error() string {
|
||||
str := "[scaleway-sdk-go] " + e.str
|
||||
if e.err != nil {
|
||||
str += ": " + e.err.Error()
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// IsScwSdkError implement SdkError interface
|
||||
func (e *Error) IsScwSdkError() {}
|
||||
|
||||
// New creates a new error with that same interface as fmt.Errorf
|
||||
func New(format string, args ...interface{}) *Error {
|
||||
return &Error{
|
||||
str: fmt.Sprintf(format, args...),
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap an error with additional information
|
||||
func Wrap(err error, format string, args ...interface{}) *Error {
|
||||
return &Error{
|
||||
err: err,
|
||||
str: fmt.Sprintf(format, args...),
|
||||
}
|
||||
}
|
139
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/marshaler/duration.go
generated
vendored
Normal file
139
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/marshaler/duration.go
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
package marshaler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Duration implements a JSON Marshaler to encode a time.Duration in milliseconds.
|
||||
type Duration int64
|
||||
|
||||
const milliSec = Duration(time.Millisecond)
|
||||
|
||||
// NewDuration converts a *time.Duration to a *Duration type.
|
||||
func NewDuration(t *time.Duration) *Duration {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
d := Duration(t.Nanoseconds())
|
||||
return &d
|
||||
}
|
||||
|
||||
// Standard converts a *Duration to a *time.Duration type.
|
||||
func (d *Duration) Standard() *time.Duration {
|
||||
return (*time.Duration)(d)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the Duration in milliseconds.
|
||||
func (d Duration) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(int64(d / milliSec))
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes milliseconds to Duration.
|
||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||
var tmp int64
|
||||
err := json.Unmarshal(b, &tmp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*d = Duration(tmp) * milliSec
|
||||
return nil
|
||||
}
|
||||
|
||||
// DurationSlice is a slice of *Duration
|
||||
type DurationSlice []*Duration
|
||||
|
||||
// NewDurationSlice converts a []*time.Duration to a DurationSlice type.
|
||||
func NewDurationSlice(t []*time.Duration) DurationSlice {
|
||||
ds := make([]*Duration, len(t))
|
||||
for i := range ds {
|
||||
ds[i] = NewDuration(t[i])
|
||||
}
|
||||
return ds
|
||||
}
|
||||
|
||||
// Standard converts a DurationSlice to a []*time.Duration type.
|
||||
func (ds *DurationSlice) Standard() []*time.Duration {
|
||||
t := make([]*time.Duration, len(*ds))
|
||||
for i := range t {
|
||||
t[i] = (*ds)[i].Standard()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// Durationint32Map is a int32 map of *Duration
|
||||
type Durationint32Map map[int32]*Duration
|
||||
|
||||
// NewDurationint32Map converts a map[int32]*time.Duration to a Durationint32Map type.
|
||||
func NewDurationint32Map(t map[int32]*time.Duration) Durationint32Map {
|
||||
dm := make(Durationint32Map, len(t))
|
||||
for i := range t {
|
||||
dm[i] = NewDuration(t[i])
|
||||
}
|
||||
return dm
|
||||
}
|
||||
|
||||
// Standard converts a Durationint32Map to a map[int32]*time.Duration type.
|
||||
func (dm *Durationint32Map) Standard() map[int32]*time.Duration {
|
||||
t := make(map[int32]*time.Duration, len(*dm))
|
||||
for key, value := range *dm {
|
||||
t[key] = value.Standard()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// LongDuration implements a JSON Marshaler to encode a time.Duration in days.
|
||||
type LongDuration int64
|
||||
|
||||
const day = LongDuration(time.Hour) * 24
|
||||
|
||||
// NewLongDuration converts a *time.Duration to a *LongDuration type.
|
||||
func NewLongDuration(t *time.Duration) *LongDuration {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
d := LongDuration(t.Nanoseconds())
|
||||
return &d
|
||||
}
|
||||
|
||||
// Standard converts a *LongDuration to a *time.Duration type.
|
||||
func (d *LongDuration) Standard() *time.Duration {
|
||||
return (*time.Duration)(d)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes the LongDuration in days.
|
||||
func (d LongDuration) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(int64(d / day))
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes days to LongDuration.
|
||||
func (d *LongDuration) UnmarshalJSON(b []byte) error {
|
||||
var tmp int64
|
||||
err := json.Unmarshal(b, &tmp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*d = LongDuration(tmp) * day
|
||||
return nil
|
||||
}
|
||||
|
||||
// LongDurationSlice is a slice of *LongDuration
|
||||
type LongDurationSlice []*LongDuration
|
||||
|
||||
// NewLongDurationSlice converts a []*time.Duration to a LongDurationSlice type.
|
||||
func NewLongDurationSlice(t []*time.Duration) LongDurationSlice {
|
||||
ds := make([]*LongDuration, len(t))
|
||||
for i := range ds {
|
||||
ds[i] = NewLongDuration(t[i])
|
||||
}
|
||||
return ds
|
||||
}
|
||||
|
||||
// Standard converts a LongDurationSlice to a []*time.Duration type.
|
||||
func (ds *LongDurationSlice) Standard() []*time.Duration {
|
||||
t := make([]*time.Duration, len(*ds))
|
||||
for i := range t {
|
||||
t[i] = (*ds)[i].Standard()
|
||||
}
|
||||
return t
|
||||
}
|
31
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/parameter/query.go
generated
vendored
Normal file
31
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/internal/parameter/query.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
package parameter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// AddToQuery add a key/value pair to an URL query
|
||||
func AddToQuery(query url.Values, key string, value interface{}) {
|
||||
elemValue := reflect.ValueOf(value)
|
||||
|
||||
if elemValue.Kind() == reflect.Invalid || elemValue.Kind() == reflect.Ptr && elemValue.IsNil() {
|
||||
return
|
||||
}
|
||||
|
||||
for elemValue.Kind() == reflect.Ptr {
|
||||
elemValue = reflect.ValueOf(value).Elem()
|
||||
}
|
||||
|
||||
elemType := elemValue.Type()
|
||||
switch {
|
||||
case elemType.Kind() == reflect.Slice:
|
||||
for i := 0; i < elemValue.Len(); i++ {
|
||||
query.Add(key, fmt.Sprint(elemValue.Index(i).Interface()))
|
||||
}
|
||||
default:
|
||||
query.Add(key, fmt.Sprint(elemValue.Interface()))
|
||||
}
|
||||
|
||||
}
|
102
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/logger/default_logger.go
generated
vendored
Normal file
102
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/logger/default_logger.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var DefaultLogger = newLogger(os.Stderr, LogLevelWarning)
|
||||
var logger Logger = DefaultLogger
|
||||
|
||||
// loggerT is the default logger used by scaleway-sdk-go.
|
||||
type loggerT struct {
|
||||
m [4]*log.Logger
|
||||
v LogLevel
|
||||
}
|
||||
|
||||
// Init create a new default logger.
|
||||
// Not mutex-protected, should be called before any scaleway-sdk-go functions.
|
||||
func (g *loggerT) Init(w io.Writer, level LogLevel) {
|
||||
g.m = newLogger(w, level).m
|
||||
}
|
||||
|
||||
// Debugf logs to the DEBUG log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Debugf(format string, args ...interface{}) { logger.Debugf(format, args...) }
|
||||
func (g *loggerT) Debugf(format string, args ...interface{}) {
|
||||
g.m[LogLevelDebug].Printf(format, args...)
|
||||
}
|
||||
|
||||
// Infof logs to the INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Infof(format string, args ...interface{}) { logger.Infof(format, args...) }
|
||||
func (g *loggerT) Infof(format string, args ...interface{}) {
|
||||
g.m[LogLevelInfo].Printf(format, args...)
|
||||
}
|
||||
|
||||
// Warningf logs to the WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Warningf(format string, args ...interface{}) { logger.Warningf(format, args...) }
|
||||
func (g *loggerT) Warningf(format string, args ...interface{}) {
|
||||
g.m[LogLevelWarning].Printf(format, args...)
|
||||
}
|
||||
|
||||
// Errorf logs to the ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Errorf(format string, args ...interface{}) { logger.Errorf(format, args...) }
|
||||
func (g *loggerT) Errorf(format string, args ...interface{}) {
|
||||
g.m[LogLevelError].Printf(format, args...)
|
||||
}
|
||||
|
||||
// ShouldLog reports whether verbosity level l is at least the requested verbose level.
|
||||
func ShouldLog(level LogLevel) bool { return logger.ShouldLog(level) }
|
||||
func (g *loggerT) ShouldLog(level LogLevel) bool {
|
||||
return level <= g.v
|
||||
}
|
||||
|
||||
func isEnabled(envKey string) bool {
|
||||
env, exist := os.LookupEnv(envKey)
|
||||
if !exist {
|
||||
return false
|
||||
}
|
||||
|
||||
value, err := strconv.ParseBool(env)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: environment variable %s has invalid boolean value\n", envKey)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// newLogger creates a logger to be used as default logger.
|
||||
// All logs are written to w.
|
||||
func newLogger(w io.Writer, level LogLevel) *loggerT {
|
||||
errorW := ioutil.Discard
|
||||
warningW := ioutil.Discard
|
||||
infoW := ioutil.Discard
|
||||
debugW := ioutil.Discard
|
||||
if isEnabled("SCW_DEBUG") {
|
||||
level = LogLevelDebug
|
||||
}
|
||||
switch level {
|
||||
case LogLevelDebug:
|
||||
debugW = w
|
||||
case LogLevelInfo:
|
||||
infoW = w
|
||||
case LogLevelWarning:
|
||||
warningW = w
|
||||
case LogLevelError:
|
||||
errorW = w
|
||||
}
|
||||
|
||||
// Error logs will be written to errorW, warningW, infoW and debugW.
|
||||
// Warning logs will be written to warningW, infoW and debugW.
|
||||
// Info logs will be written to infoW and debugW.
|
||||
// Debug logs will be written to debugW.
|
||||
var m [4]*log.Logger
|
||||
m[LogLevelError] = log.New(io.MultiWriter(debugW, infoW, warningW, errorW), severityName[LogLevelError]+": ", log.LstdFlags)
|
||||
m[LogLevelWarning] = log.New(io.MultiWriter(debugW, infoW, warningW), severityName[LogLevelWarning]+": ", log.LstdFlags)
|
||||
m[LogLevelInfo] = log.New(io.MultiWriter(debugW, infoW), severityName[LogLevelInfo]+": ", log.LstdFlags)
|
||||
m[LogLevelDebug] = log.New(debugW, severityName[LogLevelDebug]+": ", log.LstdFlags)
|
||||
return &loggerT{m: m, v: level}
|
||||
}
|
50
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/logger/logger.go
generated
vendored
Normal file
50
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/logger/logger.go
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
package logger
|
||||
|
||||
import "os"
|
||||
|
||||
type LogLevel int
|
||||
|
||||
const (
|
||||
// LogLevelDebug indicates Debug severity.
|
||||
LogLevelDebug LogLevel = iota
|
||||
// LogLevelInfo indicates Info severity.
|
||||
LogLevelInfo
|
||||
// LogLevelWarning indicates Warning severity.
|
||||
LogLevelWarning
|
||||
// LogLevelError indicates Error severity.
|
||||
LogLevelError
|
||||
)
|
||||
|
||||
// severityName contains the string representation of each severity.
|
||||
var severityName = []string{
|
||||
LogLevelDebug: "DEBUG",
|
||||
LogLevelInfo: "INFO",
|
||||
LogLevelWarning: "WARNING",
|
||||
LogLevelError: "ERROR",
|
||||
}
|
||||
|
||||
// Logger does underlying logging work for scaleway-sdk-go.
|
||||
type Logger interface {
|
||||
// Debugf logs to DEBUG log. Arguments are handled in the manner of fmt.Printf.
|
||||
Debugf(format string, args ...interface{})
|
||||
// Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
Infof(format string, args ...interface{})
|
||||
// Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
Warningf(format string, args ...interface{})
|
||||
// Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
Errorf(format string, args ...interface{})
|
||||
// ShouldLog reports whether verbosity level l is at least the requested verbose level.
|
||||
ShouldLog(level LogLevel) bool
|
||||
}
|
||||
|
||||
// SetLogger sets logger that is used in by the SDK.
|
||||
// Not mutex-protected, should be called before any scaleway-sdk-go functions.
|
||||
func SetLogger(l Logger) {
|
||||
logger = l
|
||||
}
|
||||
|
||||
// EnableDebugMode enable LogLevelDebug on the default logger.
|
||||
// If a custom logger was provided with SetLogger this method has no effect.
|
||||
func EnableDebugMode() {
|
||||
DefaultLogger.Init(os.Stderr, LogLevelDebug)
|
||||
}
|
304
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/client.go
generated
vendored
Normal file
304
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/client.go
generated
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
package scw
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/auth"
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/errors"
|
||||
"github.com/scaleway/scaleway-sdk-go/logger"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
)
|
||||
|
||||
// Client is the Scaleway client which performs API requests.
|
||||
//
|
||||
// This client should be passed in the `NewApi` functions whenever an API instance is created.
|
||||
// Creating a Client is done with the `NewClient` function.
|
||||
type Client struct {
|
||||
httpClient httpClient
|
||||
auth auth.Auth
|
||||
apiURL string
|
||||
userAgent string
|
||||
defaultProjectID *string
|
||||
defaultRegion *utils.Region
|
||||
defaultZone *utils.Zone
|
||||
defaultPageSize *int32
|
||||
}
|
||||
|
||||
func defaultOptions() []ClientOption {
|
||||
return []ClientOption{
|
||||
WithAPIURL("https://api.scaleway.com"),
|
||||
withDefaultUserAgent(userAgent),
|
||||
}
|
||||
}
|
||||
|
||||
// NewClient instantiate a new Client object.
|
||||
//
|
||||
// Zero or more ClientOption object can be passed as a parameter.
|
||||
// These options will then be applied to the client.
|
||||
func NewClient(opts ...ClientOption) (*Client, error) {
|
||||
s := newSettings()
|
||||
|
||||
// apply options
|
||||
s.apply(append(defaultOptions(), opts...))
|
||||
|
||||
// validate settings
|
||||
err := s.validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// dial the API
|
||||
if s.httpClient == nil {
|
||||
s.httpClient = newHTTPClient()
|
||||
}
|
||||
|
||||
// insecure mode
|
||||
if s.insecure {
|
||||
logger.Debugf("client: using insecure mode")
|
||||
setInsecureMode(s.httpClient)
|
||||
}
|
||||
|
||||
logger.Debugf("client: using sdk version " + version)
|
||||
|
||||
return &Client{
|
||||
auth: s.token,
|
||||
httpClient: s.httpClient,
|
||||
apiURL: s.apiURL,
|
||||
userAgent: s.userAgent,
|
||||
defaultProjectID: s.defaultProjectID,
|
||||
defaultRegion: s.defaultRegion,
|
||||
defaultZone: s.defaultZone,
|
||||
defaultPageSize: s.defaultPageSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetDefaultProjectID return the default project ID
|
||||
// of the client. This value can be set in the client option
|
||||
// WithDefaultProjectID(). Be aware this value can be empty.
|
||||
func (c *Client) GetDefaultProjectID() (string, bool) {
|
||||
if c.defaultProjectID != nil {
|
||||
return *c.defaultProjectID, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// GetDefaultRegion return the default region of the client.
|
||||
// This value can be set in the client option
|
||||
// WithDefaultRegion(). Be aware this value can be empty.
|
||||
func (c *Client) GetDefaultRegion() (utils.Region, bool) {
|
||||
if c.defaultRegion != nil {
|
||||
return *c.defaultRegion, true
|
||||
}
|
||||
return utils.Region(""), false
|
||||
}
|
||||
|
||||
// GetDefaultZone return the default zone of the client.
|
||||
// This value can be set in the client option
|
||||
// WithDefaultZone(). Be aware this value can be empty.
|
||||
func (c *Client) GetDefaultZone() (utils.Zone, bool) {
|
||||
if c.defaultZone != nil {
|
||||
return *c.defaultZone, true
|
||||
}
|
||||
return utils.Zone(""), false
|
||||
}
|
||||
|
||||
// GetDefaultPageSize return the default page size of the client.
|
||||
// This value can be set in the client option
|
||||
// WithDefaultPageSize(). Be aware this value can be empty.
|
||||
func (c *Client) GetDefaultPageSize() (int32, bool) {
|
||||
if c.defaultPageSize != nil {
|
||||
return *c.defaultPageSize, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// Do performs HTTP request(s) based on the ScalewayRequest object.
|
||||
// RequestOptions are applied prior to doing the request.
|
||||
func (c *Client) Do(req *ScalewayRequest, res interface{}, opts ...RequestOption) (err error) {
|
||||
requestSettings := newRequestSettings()
|
||||
|
||||
// apply request options
|
||||
requestSettings.apply(opts)
|
||||
|
||||
// validate request options
|
||||
err = requestSettings.validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if requestSettings.ctx != nil {
|
||||
req.Ctx = requestSettings.ctx
|
||||
}
|
||||
|
||||
if requestSettings.allPages {
|
||||
return c.doListAll(req, res)
|
||||
}
|
||||
|
||||
return c.do(req, res)
|
||||
}
|
||||
|
||||
// requestNumber auto increments on each do().
|
||||
// This allows easy distinguishing of concurrently performed requests in log.
|
||||
var requestNumber uint32
|
||||
|
||||
// do performs a single HTTP request based on the ScalewayRequest object.
|
||||
func (c *Client) do(req *ScalewayRequest, res interface{}) (sdkErr SdkError) {
|
||||
|
||||
currentRequestNumber := atomic.AddUint32(&requestNumber, 1)
|
||||
|
||||
if req == nil {
|
||||
return errors.New("request must be non-nil")
|
||||
}
|
||||
|
||||
// build url
|
||||
url, sdkErr := req.getURL(c.apiURL)
|
||||
if sdkErr != nil {
|
||||
return sdkErr
|
||||
}
|
||||
logger.Debugf("creating %s request on %s", req.Method, url.String())
|
||||
|
||||
// build request
|
||||
httpRequest, err := http.NewRequest(req.Method, url.String(), req.Body)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not create request")
|
||||
}
|
||||
|
||||
httpRequest.Header = req.getAllHeaders(c.auth, c.userAgent, false)
|
||||
|
||||
if req.Ctx != nil {
|
||||
httpRequest = httpRequest.WithContext(req.Ctx)
|
||||
}
|
||||
|
||||
if logger.ShouldLog(logger.LogLevelDebug) {
|
||||
|
||||
// Keep original headers (before anonymization)
|
||||
originalHeaders := httpRequest.Header
|
||||
|
||||
// Get anonymized headers
|
||||
httpRequest.Header = req.getAllHeaders(c.auth, c.userAgent, true)
|
||||
|
||||
dump, err := httputil.DumpRequestOut(httpRequest, true)
|
||||
if err != nil {
|
||||
logger.Warningf("cannot dump outgoing request: %s", err)
|
||||
} else {
|
||||
var logString string
|
||||
logString += "\n--------------- Scaleway SDK REQUEST %d : ---------------\n"
|
||||
logString += "%s\n"
|
||||
logString += "---------------------------------------------------------"
|
||||
|
||||
logger.Debugf(logString, currentRequestNumber, dump)
|
||||
}
|
||||
|
||||
// Restore original headers before sending the request
|
||||
httpRequest.Header = originalHeaders
|
||||
}
|
||||
|
||||
// execute request
|
||||
httpResponse, err := c.httpClient.Do(httpRequest)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error executing request")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
closeErr := httpResponse.Body.Close()
|
||||
if sdkErr == nil && closeErr != nil {
|
||||
sdkErr = errors.Wrap(closeErr, "could not close http response")
|
||||
}
|
||||
}()
|
||||
if logger.ShouldLog(logger.LogLevelDebug) {
|
||||
dump, err := httputil.DumpResponse(httpResponse, true)
|
||||
if err != nil {
|
||||
logger.Warningf("cannot dump ingoing response: %s", err)
|
||||
} else {
|
||||
var logString string
|
||||
logString += "\n--------------- Scaleway SDK RESPONSE %d : ---------------\n"
|
||||
logString += "%s\n"
|
||||
logString += "----------------------------------------------------------"
|
||||
|
||||
logger.Debugf(logString, currentRequestNumber, dump)
|
||||
}
|
||||
}
|
||||
|
||||
sdkErr = hasResponseError(httpResponse)
|
||||
if sdkErr != nil {
|
||||
return sdkErr
|
||||
}
|
||||
|
||||
if res != nil {
|
||||
err = json.NewDecoder(httpResponse.Body).Decode(&res)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not parse response body")
|
||||
}
|
||||
|
||||
// Handle instance API X-Total-Count header
|
||||
xTotalCountStr := httpResponse.Header.Get("X-Total-Count")
|
||||
if legacyLister, isLegacyLister := res.(legacyLister); isLegacyLister && xTotalCountStr != "" {
|
||||
xTotalCount, err := strconv.Atoi(xTotalCountStr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not parse X-Total-Count header")
|
||||
}
|
||||
legacyLister.UnsafeSetTotalCount(xTotalCount)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newHTTPClient() *http.Client {
|
||||
return &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{Timeout: 5 * time.Second}).DialContext,
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
ResponseHeaderTimeout: 30 * time.Second,
|
||||
MaxIdleConnsPerHost: 20,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func setInsecureMode(c httpClient) {
|
||||
standardHTTPClient, ok := c.(*http.Client)
|
||||
if !ok {
|
||||
logger.Warningf("client: cannot use insecure mode with HTTP client of type %T", c)
|
||||
return
|
||||
}
|
||||
transportClient, ok := standardHTTPClient.Transport.(*http.Transport)
|
||||
if !ok {
|
||||
logger.Warningf("client: cannot use insecure mode with Transport client of type %T", standardHTTPClient.Transport)
|
||||
return
|
||||
}
|
||||
if transportClient.TLSClientConfig == nil {
|
||||
transportClient.TLSClientConfig = &tls.Config{}
|
||||
}
|
||||
transportClient.TLSClientConfig.InsecureSkipVerify = true
|
||||
}
|
||||
|
||||
func hasResponseError(res *http.Response) SdkError {
|
||||
if res.StatusCode >= 200 && res.StatusCode <= 299 {
|
||||
return nil
|
||||
}
|
||||
|
||||
newErr := &ResponseError{
|
||||
StatusCode: res.StatusCode,
|
||||
Status: res.Status,
|
||||
}
|
||||
|
||||
if res.Body == nil {
|
||||
return newErr
|
||||
}
|
||||
|
||||
err := json.NewDecoder(res.Body).Decode(newErr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not parse error response body")
|
||||
}
|
||||
|
||||
return newErr
|
||||
}
|
142
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/client_option.go
generated
vendored
Normal file
142
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/client_option.go
generated
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
package scw
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/auth"
|
||||
"github.com/scaleway/scaleway-sdk-go/scwconfig"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
)
|
||||
|
||||
// ClientOption is a function which applies options to a settings object.
|
||||
type ClientOption func(*settings)
|
||||
|
||||
// httpClient wraps the net/http Client Do method
|
||||
type httpClient interface {
|
||||
Do(*http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// WithHTTPClient client option allows passing a custom http.Client which will be used for all requests.
|
||||
func WithHTTPClient(httpClient httpClient) ClientOption {
|
||||
return func(s *settings) {
|
||||
s.httpClient = httpClient
|
||||
}
|
||||
}
|
||||
|
||||
// WithoutAuth client option sets the client token to an empty token.
|
||||
func WithoutAuth() ClientOption {
|
||||
return func(s *settings) {
|
||||
s.token = auth.NewNoAuth()
|
||||
}
|
||||
}
|
||||
|
||||
// WithAuth client option sets the client access key and secret key.
|
||||
func WithAuth(accessKey, secretKey string) ClientOption {
|
||||
return func(s *settings) {
|
||||
s.token = auth.NewToken(accessKey, secretKey)
|
||||
}
|
||||
}
|
||||
|
||||
// WithAPIURL client option overrides the API URL of the Scaleway API to the given URL.
|
||||
func WithAPIURL(apiURL string) ClientOption {
|
||||
return func(s *settings) {
|
||||
s.apiURL = apiURL
|
||||
}
|
||||
}
|
||||
|
||||
// WithInsecure client option enables insecure transport on the client.
|
||||
func WithInsecure() ClientOption {
|
||||
return func(s *settings) {
|
||||
s.insecure = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithUserAgent client option append a user agent to the default user agent of the SDK.
|
||||
func WithUserAgent(ua string) ClientOption {
|
||||
return func(s *settings) {
|
||||
if s.userAgent != "" && ua != "" {
|
||||
s.userAgent += " "
|
||||
}
|
||||
s.userAgent += ua
|
||||
}
|
||||
}
|
||||
|
||||
// withDefaultUserAgent client option overrides the default user agent of the SDK.
|
||||
func withDefaultUserAgent(ua string) ClientOption {
|
||||
return func(s *settings) {
|
||||
s.userAgent = ua
|
||||
}
|
||||
}
|
||||
|
||||
// WithConfig client option configure a client with Scaleway configuration.
|
||||
func WithConfig(config scwconfig.Config) ClientOption {
|
||||
return func(s *settings) {
|
||||
// The access key is not used for API authentications.
|
||||
accessKey, _ := config.GetAccessKey()
|
||||
secretKey, secretKeyExist := config.GetSecretKey()
|
||||
if secretKeyExist {
|
||||
s.token = auth.NewToken(accessKey, secretKey)
|
||||
}
|
||||
|
||||
apiURL, exist := config.GetAPIURL()
|
||||
if exist {
|
||||
s.apiURL = apiURL
|
||||
}
|
||||
|
||||
insecure, exist := config.GetInsecure()
|
||||
if exist {
|
||||
s.insecure = insecure
|
||||
}
|
||||
|
||||
defaultProjectID, exist := config.GetDefaultProjectID()
|
||||
if exist {
|
||||
s.defaultProjectID = &defaultProjectID
|
||||
}
|
||||
|
||||
defaultRegion, exist := config.GetDefaultRegion()
|
||||
if exist {
|
||||
s.defaultRegion = &defaultRegion
|
||||
}
|
||||
|
||||
defaultZone, exist := config.GetDefaultZone()
|
||||
if exist {
|
||||
s.defaultZone = &defaultZone
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithDefaultProjectID client option sets the client default project ID.
|
||||
//
|
||||
// It will be used as the default value of the project_id field in all requests made with this client.
|
||||
func WithDefaultProjectID(projectID string) ClientOption {
|
||||
return func(s *settings) {
|
||||
s.defaultProjectID = &projectID
|
||||
}
|
||||
}
|
||||
|
||||
// WithDefaultRegion client option sets the client default region.
|
||||
//
|
||||
// It will be used as the default value of the region field in all requests made with this client.
|
||||
func WithDefaultRegion(region utils.Region) ClientOption {
|
||||
return func(s *settings) {
|
||||
s.defaultRegion = ®ion
|
||||
}
|
||||
}
|
||||
|
||||
// WithDefaultZone client option sets the client default zone.
|
||||
//
|
||||
// It will be used as the default value of the zone field in all requests made with this client.
|
||||
func WithDefaultZone(zone utils.Zone) ClientOption {
|
||||
return func(s *settings) {
|
||||
s.defaultZone = &zone
|
||||
}
|
||||
}
|
||||
|
||||
// WithDefaultPageSize client option overrides the default page size of the SDK.
|
||||
//
|
||||
// It will be used as the default value of the page_size field in all requests made with this client.
|
||||
func WithDefaultPageSize(pageSize int32) ClientOption {
|
||||
return func(s *settings) {
|
||||
s.defaultPageSize = &pageSize
|
||||
}
|
||||
}
|
46
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/errors.go
generated
vendored
Normal file
46
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/errors.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
package scw
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// SdkError is a base interface for all Scaleway SDK errors.
|
||||
type SdkError interface {
|
||||
Error() string
|
||||
IsScwSdkError()
|
||||
}
|
||||
|
||||
// ResponseError is an error type for the Scaleway API
|
||||
type ResponseError struct {
|
||||
// Message is a human-friendly error message
|
||||
Message string `json:"message"`
|
||||
|
||||
// Type is a string code that defines the kind of error
|
||||
Type string `json:"type,omitempty"`
|
||||
|
||||
// Fields contains detail about validation error
|
||||
Fields map[string][]string `json:"fields,omitempty"`
|
||||
|
||||
// StatusCode is the HTTP status code received
|
||||
StatusCode int `json:"-"`
|
||||
|
||||
// Status is the HTTP status received
|
||||
Status string `json:"-"`
|
||||
}
|
||||
|
||||
func (e *ResponseError) Error() string {
|
||||
s := fmt.Sprintf("scaleway-sdk-go: http error %s", e.Status)
|
||||
|
||||
if e.Message != "" {
|
||||
s = fmt.Sprintf("%s: %s", s, e.Message)
|
||||
}
|
||||
|
||||
if len(e.Fields) > 0 {
|
||||
s = fmt.Sprintf("%s: %v", s, e.Fields)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// IsScwSdkError implement SdkError interface
|
||||
func (e *ResponseError) IsScwSdkError() {}
|
64
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/lister.go
generated
vendored
Normal file
64
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/lister.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
package scw
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/errors"
|
||||
)
|
||||
|
||||
type lister interface {
|
||||
UnsafeGetTotalCount() int
|
||||
UnsafeAppend(interface{}) (int, SdkError)
|
||||
}
|
||||
|
||||
type legacyLister interface {
|
||||
UnsafeSetTotalCount(totalCount int)
|
||||
}
|
||||
|
||||
// doListAll collects all pages of a List request and aggregate all results on a single response.
|
||||
func (c *Client) doListAll(req *ScalewayRequest, res interface{}) (err SdkError) {
|
||||
|
||||
// check for lister interface
|
||||
if response, isLister := res.(lister); isLister {
|
||||
|
||||
pageCount := math.MaxUint32
|
||||
for page := 1; page <= pageCount; page++ {
|
||||
// set current page
|
||||
req.Query.Set("page", strconv.Itoa(page))
|
||||
|
||||
// request the next page
|
||||
nextPage := newPage(response)
|
||||
err := c.do(req, nextPage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// append results
|
||||
pageSize, err := response.UnsafeAppend(nextPage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if pageSize == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// set total count on first request
|
||||
if pageCount == math.MaxUint32 {
|
||||
totalCount := nextPage.(lister).UnsafeGetTotalCount()
|
||||
pageCount = (totalCount + pageSize - 1) / pageSize
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("%T does not support pagination", res)
|
||||
}
|
||||
|
||||
// newPage returns a variable set to the zero value of the given type
|
||||
func newPage(v interface{}) interface{} {
|
||||
// reflect.New always create a pointer, that's why we use reflect.Indirect before
|
||||
return reflect.New(reflect.Indirect(reflect.ValueOf(v)).Type()).Interface()
|
||||
}
|
82
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/request.go
generated
vendored
Normal file
82
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/request.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
package scw
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/auth"
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/errors"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
)
|
||||
|
||||
// ScalewayRequest contains all the contents related to performing a request on the Scaleway API.
|
||||
type ScalewayRequest struct {
|
||||
Method string
|
||||
Path string
|
||||
Headers http.Header
|
||||
Query url.Values
|
||||
Body io.Reader
|
||||
Ctx context.Context
|
||||
}
|
||||
|
||||
// getAllHeaders constructs a http.Header object and aggregates all headers into the object.
|
||||
func (req *ScalewayRequest) getAllHeaders(token auth.Auth, userAgent string, anonymized bool) http.Header {
|
||||
var allHeaders http.Header
|
||||
if anonymized {
|
||||
allHeaders = token.AnonymizedHeaders()
|
||||
} else {
|
||||
allHeaders = token.Headers()
|
||||
}
|
||||
|
||||
allHeaders.Set("User-Agent", userAgent)
|
||||
if req.Body != nil {
|
||||
allHeaders.Set("content-type", "application/json")
|
||||
}
|
||||
for key, value := range req.Headers {
|
||||
for _, v := range value {
|
||||
allHeaders.Set(key, v)
|
||||
}
|
||||
}
|
||||
|
||||
return allHeaders
|
||||
}
|
||||
|
||||
// getURL constructs a URL based on the base url and the client.
|
||||
func (req *ScalewayRequest) getURL(baseURL string) (*url.URL, SdkError) {
|
||||
url, err := url.Parse(baseURL + req.Path)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid url %s: %s", baseURL+req.Path, err)
|
||||
}
|
||||
url.RawQuery = req.Query.Encode()
|
||||
|
||||
return url, nil
|
||||
}
|
||||
|
||||
// SetBody json marshal the given body and write the json content type
|
||||
// to the request. It also catches when body is a file.
|
||||
func (req *ScalewayRequest) SetBody(body interface{}) error {
|
||||
var contentType string
|
||||
var content io.Reader
|
||||
|
||||
switch b := body.(type) {
|
||||
case *utils.File:
|
||||
contentType = b.ContentType
|
||||
content = b.Content
|
||||
default:
|
||||
buf, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
contentType = "application/json"
|
||||
content = bytes.NewReader(buf)
|
||||
}
|
||||
|
||||
req.Headers.Set("Content-Type", contentType)
|
||||
req.Body = content
|
||||
|
||||
return nil
|
||||
}
|
43
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/request_option.go
generated
vendored
Normal file
43
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/request_option.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
package scw
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// RequestOption is a function that applies options to a ScalewayRequest.
|
||||
type RequestOption func(*requestSettings)
|
||||
|
||||
// WithContext request option sets the context of a ScalewayRequest
|
||||
func WithContext(ctx context.Context) RequestOption {
|
||||
return func(s *requestSettings) {
|
||||
s.ctx = ctx
|
||||
}
|
||||
}
|
||||
|
||||
// WithAllPages aggregate all pages in the response of a List request.
|
||||
// Will error when pagination is not supported on the request.
|
||||
func WithAllPages() RequestOption {
|
||||
return func(s *requestSettings) {
|
||||
s.allPages = true
|
||||
}
|
||||
}
|
||||
|
||||
type requestSettings struct {
|
||||
ctx context.Context
|
||||
allPages bool
|
||||
}
|
||||
|
||||
func newRequestSettings() *requestSettings {
|
||||
return &requestSettings{}
|
||||
}
|
||||
|
||||
func (s *requestSettings) apply(opts []RequestOption) {
|
||||
for _, opt := range opts {
|
||||
opt(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *requestSettings) validate() SdkError {
|
||||
// nothing so far
|
||||
return nil
|
||||
}
|
64
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/settings.go
generated
vendored
Normal file
64
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/settings.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
package scw
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/internal/auth"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
)
|
||||
|
||||
type settings struct {
|
||||
apiURL string
|
||||
token auth.Auth
|
||||
userAgent string
|
||||
httpClient httpClient
|
||||
insecure bool
|
||||
defaultProjectID *string
|
||||
defaultRegion *utils.Region
|
||||
defaultZone *utils.Zone
|
||||
defaultPageSize *int32
|
||||
}
|
||||
|
||||
func newSettings() *settings {
|
||||
return &settings{}
|
||||
}
|
||||
|
||||
func (s *settings) apply(opts []ClientOption) {
|
||||
for _, opt := range opts {
|
||||
opt(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *settings) validate() error {
|
||||
var err error
|
||||
if s.token == nil {
|
||||
return fmt.Errorf("no credential option provided")
|
||||
}
|
||||
|
||||
_, err = url.Parse(s.apiURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid url %s: %s", s.apiURL, err)
|
||||
}
|
||||
|
||||
// TODO: Check ProjectID format
|
||||
if s.defaultProjectID != nil && *s.defaultProjectID == "" {
|
||||
return fmt.Errorf("default project id cannot be empty")
|
||||
}
|
||||
|
||||
// TODO: Check Region format
|
||||
if s.defaultRegion != nil && *s.defaultRegion == "" {
|
||||
return fmt.Errorf("default region cannot be empty")
|
||||
}
|
||||
|
||||
// TODO: Check Zone format
|
||||
if s.defaultZone != nil && *s.defaultZone == "" {
|
||||
return fmt.Errorf("default zone cannot be empty")
|
||||
}
|
||||
|
||||
if s.defaultPageSize != nil && *s.defaultPageSize <= 0 {
|
||||
return fmt.Errorf("default page size cannot be <= 0")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
11
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/version.go
generated
vendored
Normal file
11
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scw/version.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package scw
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// TODO: versionning process
|
||||
const version = "0.0.0"
|
||||
|
||||
var userAgent = fmt.Sprintf("scaleway-sdk-go/%s (%s; %s; %s)", version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
48
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/README.md
generated
vendored
Normal file
48
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/README.md
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
# Scaleway config
|
||||
|
||||
## TL;DR
|
||||
|
||||
Recommended config file:
|
||||
|
||||
```yaml
|
||||
# get your credentials on https://console.scaleway.com/account/credentials
|
||||
access_key: SCWXXXXXXXXXXXXXXXXX
|
||||
secret_key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
default_project_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
default_region: fr-par
|
||||
default_zone: fr-par-1
|
||||
```
|
||||
|
||||
## Config file path
|
||||
|
||||
This package will try to locate the config file in the following ways:
|
||||
|
||||
1. Custom directory: `$SCW_CONFIG_PATH`
|
||||
2. [XDG base directory](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html): `$XDG_CONFIG_HOME/scw/config.yaml`
|
||||
3. Home directory: `$HOME/.config/scw/config.yaml` (`%USERPROFILE%/.config/scw/config.yaml` on windows)
|
||||
|
||||
## V1 config (DEPRECATED)
|
||||
|
||||
The V1 config `.scwrc` is supported but deprecated.
|
||||
When found in the home directory, the V1 config is automatically migrated to a V2 config file in `$HOME/.config/scw/config.yaml`.
|
||||
|
||||
## Reading config order
|
||||
|
||||
When getting the value of a config field, the following priority order will be respected:
|
||||
|
||||
1. Environment variable
|
||||
2. Legacy environment variable
|
||||
3. Config file V2
|
||||
4. Config file V1
|
||||
|
||||
## Environment variables
|
||||
|
||||
| Variable | Description | Legacy variables |
|
||||
| :------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------ |
|
||||
| `$SCW_ACCESS_KEY` | Access key of a token ([get yours](https://console.scaleway.com/account/credentials)) | `$SCALEWAY_ACCESS_KEY` (used by terraform) |
|
||||
| `$SCW_SECRET_KEY` | Secret key of a token ([get yours](https://console.scaleway.com/account/credentials)) | `$SCW_TOKEN` (used by cli), `$SCALEWAY_TOKEN` (used by terraform), `$SCALEWAY_ACCESS_KEY` (used by terraform) |
|
||||
| `$SCW_DEFAULT_PROJECT_ID` | Your default project ID, if you don't have one use your organization ID ([get yours](https://console.scaleway.com/account/credentials)) | `$SCW_ORGANIZATION` (used by cli),`$SCALEWAY_ORGANIZATION` (used by terraform) |
|
||||
| `$SCW_DEFAULT_REGION` | Your default [region](https://developers.scaleway.com/en/quickstart/#region-and-zone) | `$SCW_REGION` (used by cli),`$SCALEWAY_REGION` (used by terraform) |
|
||||
| `$SCW_DEFAULT_ZONE` | Your default [availability zone](https://developers.scaleway.com/en/quickstart/#region-and-zone) | `$SCW_ZONE` (used by cli),`$SCALEWAY_ZONE` (used by terraform) |
|
||||
| `$SCW_API_URL` | Url of the API | - |
|
||||
| `$SCW_INSECURE` | Set this to `true` to enable the insecure mode | `$SCW_TLSVERIFY` (inverse flag used by the cli) |
|
423
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/config.go
generated
vendored
Normal file
423
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/config.go
generated
vendored
Normal file
@ -0,0 +1,423 @@
|
||||
package scwconfig
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/logger"
|
||||
"github.com/scaleway/scaleway-sdk-go/utils"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Environment variables
|
||||
const (
|
||||
// Up-to-date
|
||||
scwConfigPathEnv = "SCW_CONFIG_PATH"
|
||||
scwAccessKeyEnv = "SCW_ACCESS_KEY"
|
||||
scwSecretKeyEnv = "SCW_SECRET_KEY"
|
||||
scwActiveProfileEnv = "SCW_PROFILE"
|
||||
scwAPIURLEnv = "SCW_API_URL"
|
||||
scwInsecureEnv = "SCW_INSECURE"
|
||||
scwDefaultProjectIDEnv = "SCW_DEFAULT_PROJECT_ID"
|
||||
scwDefaultRegionEnv = "SCW_DEFAULT_REGION"
|
||||
scwDefaultZoneEnv = "SCW_DEFAULT_ZONE"
|
||||
|
||||
// All deprecated (cli&terraform)
|
||||
terraformAccessKeyEnv = "SCALEWAY_ACCESS_KEY" // used both as access key and secret key
|
||||
terraformSecretKeyEnv = "SCALEWAY_TOKEN"
|
||||
terraformOrganizationEnv = "SCALEWAY_ORGANIZATION"
|
||||
terraformRegionEnv = "SCALEWAY_REGION"
|
||||
cliTLSVerifyEnv = "SCW_TLSVERIFY"
|
||||
cliOrganizationEnv = "SCW_ORGANIZATION"
|
||||
cliRegionEnv = "SCW_REGION"
|
||||
cliSecretKeyEnv = "SCW_TOKEN"
|
||||
|
||||
// TBD
|
||||
//cliVerboseEnv = "SCW_VERBOSE_API"
|
||||
//cliDebugEnv = "DEBUG"
|
||||
//cliNoCheckVersionEnv = "SCW_NOCHECKVERSION"
|
||||
//cliTestWithRealAPIEnv = "TEST_WITH_REAL_API"
|
||||
//cliSecureExecEnv = "SCW_SECURE_EXEC"
|
||||
//cliGatewayEnv = "SCW_GATEWAY"
|
||||
//cliSensitiveEnv = "SCW_SENSITIVE"
|
||||
//cliAccountAPIEnv = "SCW_ACCOUNT_API"
|
||||
//cliMetadataAPIEnv = "SCW_METADATA_API"
|
||||
//cliMarketPlaceAPIEnv = "SCW_MARKETPLACE_API"
|
||||
//cliComputePar1APIEnv = "SCW_COMPUTE_PAR1_API"
|
||||
//cliComputeAms1APIEnv = "SCW_COMPUTE_AMS1_API"
|
||||
//cliCommercialTypeEnv = "SCW_COMMERCIAL_TYPE"
|
||||
//cliTargetArchEnv = "SCW_TARGET_ARCH"
|
||||
)
|
||||
|
||||
// Config interface is made of getters to retrieve
|
||||
// the config field by field.
|
||||
type Config interface {
|
||||
GetAccessKey() (accessKey string, exist bool)
|
||||
GetSecretKey() (secretKey string, exist bool)
|
||||
GetAPIURL() (apiURL string, exist bool)
|
||||
GetInsecure() (insecure bool, exist bool)
|
||||
GetDefaultProjectID() (defaultProjectID string, exist bool)
|
||||
GetDefaultRegion() (defaultRegion utils.Region, exist bool)
|
||||
GetDefaultZone() (defaultZone utils.Zone, exist bool)
|
||||
}
|
||||
|
||||
type configV2 struct {
|
||||
profile `yaml:",inline"`
|
||||
ActiveProfile *string `yaml:"active_profile,omitempty"`
|
||||
Profiles map[string]*profile `yaml:"profiles,omitempty"`
|
||||
|
||||
// withProfile is used by LoadWithProfile to handle the following priority order:
|
||||
// c.withProfile > os.Getenv("SCW_PROFILE") > c.ActiveProfile
|
||||
withProfile string
|
||||
}
|
||||
|
||||
type profile struct {
|
||||
AccessKey *string `yaml:"access_key,omitempty"`
|
||||
SecretKey *string `yaml:"secret_key,omitempty"`
|
||||
APIURL *string `yaml:"api_url,omitempty"`
|
||||
Insecure *bool `yaml:"insecure,omitempty"`
|
||||
DefaultProjectID *string `yaml:"default_project_id,omitempty"`
|
||||
DefaultRegion *string `yaml:"default_region,omitempty"`
|
||||
DefaultZone *string `yaml:"default_zone,omitempty"`
|
||||
}
|
||||
|
||||
func unmarshalConfV2(content []byte) (*configV2, error) {
|
||||
var config configV2
|
||||
|
||||
err := yaml.Unmarshal(content, &config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
func (c *configV2) catchInvalidProfile() (*configV2, error) {
|
||||
activeProfile, err := c.getActiveProfile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if activeProfile == "" {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
_, exist := c.Profiles[activeProfile]
|
||||
if !exist {
|
||||
return nil, fmt.Errorf("profile %s does not exist %s", activeProfile, inConfigFile())
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *configV2) getActiveProfile() (string, error) {
|
||||
switch {
|
||||
case c.withProfile != "":
|
||||
return c.withProfile, nil
|
||||
case os.Getenv(scwActiveProfileEnv) != "":
|
||||
return os.Getenv(scwActiveProfileEnv), nil
|
||||
case c.ActiveProfile != nil:
|
||||
if *c.ActiveProfile == "" {
|
||||
return "", fmt.Errorf("active_profile key cannot be empty %s", inConfigFile())
|
||||
}
|
||||
return *c.ActiveProfile, nil
|
||||
default:
|
||||
return "", nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetAccessKey retrieve the access key from the config.
|
||||
// It will check the following order:
|
||||
// env, legacy env, active profile, default profile
|
||||
//
|
||||
// If the config is present in one of the above environment the
|
||||
// value (which may be empty) is returned and the boolean is true.
|
||||
// Otherwise the returned value will be empty and the boolean will
|
||||
// be false.
|
||||
func (c *configV2) GetAccessKey() (string, bool) {
|
||||
envValue, _, envExist := getenv(scwAccessKeyEnv, terraformAccessKeyEnv)
|
||||
activeProfile, _ := c.getActiveProfile()
|
||||
|
||||
var accessKey string
|
||||
switch {
|
||||
case envExist:
|
||||
accessKey = envValue
|
||||
case activeProfile != "" && c.Profiles[activeProfile].AccessKey != nil:
|
||||
accessKey = *c.Profiles[activeProfile].AccessKey
|
||||
case c.AccessKey != nil:
|
||||
accessKey = *c.AccessKey
|
||||
default:
|
||||
logger.Warningf("no access key found")
|
||||
return "", false
|
||||
}
|
||||
|
||||
if accessKey == "" {
|
||||
logger.Warningf("access key is empty")
|
||||
}
|
||||
|
||||
return accessKey, true
|
||||
}
|
||||
|
||||
// GetSecretKey retrieve the secret key from the config.
|
||||
// It will check the following order:
|
||||
// env, legacy env, active profile, default profile
|
||||
//
|
||||
// If the config is present in one of the above environment the
|
||||
// value (which may be empty) is returned and the boolean is true.
|
||||
// Otherwise the returned value will be empty and the boolean will
|
||||
// be false.
|
||||
func (c *configV2) GetSecretKey() (string, bool) {
|
||||
envValue, _, envExist := getenv(scwSecretKeyEnv, cliSecretKeyEnv, terraformSecretKeyEnv, terraformAccessKeyEnv)
|
||||
activeProfile, _ := c.getActiveProfile()
|
||||
|
||||
var secretKey string
|
||||
switch {
|
||||
case envExist:
|
||||
secretKey = envValue
|
||||
case activeProfile != "" && c.Profiles[activeProfile].SecretKey != nil:
|
||||
secretKey = *c.Profiles[activeProfile].SecretKey
|
||||
case c.SecretKey != nil:
|
||||
secretKey = *c.SecretKey
|
||||
default:
|
||||
logger.Warningf("no secret key found")
|
||||
return "", false
|
||||
}
|
||||
|
||||
if secretKey == "" {
|
||||
logger.Warningf("secret key is empty")
|
||||
}
|
||||
|
||||
return secretKey, true
|
||||
}
|
||||
|
||||
// GetAPIURL retrieve the api url from the config.
|
||||
// It will check the following order:
|
||||
// env, legacy env, active profile, default profile
|
||||
//
|
||||
// If the config is present in one of the above environment the
|
||||
// value (which may be empty) is returned and the boolean is true.
|
||||
// Otherwise the returned value will be empty and the boolean will
|
||||
// be false.
|
||||
func (c *configV2) GetAPIURL() (string, bool) {
|
||||
envValue, _, envExist := getenv(scwAPIURLEnv)
|
||||
activeProfile, _ := c.getActiveProfile()
|
||||
|
||||
var apiURL string
|
||||
switch {
|
||||
case envExist:
|
||||
apiURL = envValue
|
||||
case activeProfile != "" && c.Profiles[activeProfile].APIURL != nil:
|
||||
apiURL = *c.Profiles[activeProfile].APIURL
|
||||
case c.APIURL != nil:
|
||||
apiURL = *c.APIURL
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
|
||||
if apiURL == "" {
|
||||
logger.Warningf("api URL is empty")
|
||||
}
|
||||
|
||||
return apiURL, true
|
||||
}
|
||||
|
||||
// GetInsecure retrieve the insecure flag from the config.
|
||||
// It will check the following order:
|
||||
// env, legacy env, active profile, default profile
|
||||
//
|
||||
// If the config is present in one of the above environment the
|
||||
// value (which may be empty) is returned and the boolean is true.
|
||||
// Otherwise the returned value will be empty and the boolean will
|
||||
// be false.
|
||||
func (c *configV2) GetInsecure() (bool, bool) {
|
||||
envValue, envKey, envExist := getenv(scwInsecureEnv, cliTLSVerifyEnv)
|
||||
activeProfile, _ := c.getActiveProfile()
|
||||
|
||||
var insecure bool
|
||||
var err error
|
||||
switch {
|
||||
case envExist:
|
||||
insecure, err = strconv.ParseBool(envValue)
|
||||
if err != nil {
|
||||
logger.Warningf("env variable %s cannot be parsed: %s is invalid boolean ", envKey, envValue)
|
||||
return false, false
|
||||
}
|
||||
|
||||
if envKey == cliTLSVerifyEnv {
|
||||
insecure = !insecure // TLSVerify is the inverse of Insecure
|
||||
}
|
||||
case activeProfile != "" && c.Profiles[activeProfile].Insecure != nil:
|
||||
insecure = *c.Profiles[activeProfile].Insecure
|
||||
case c.Insecure != nil:
|
||||
insecure = *c.Insecure
|
||||
default:
|
||||
return false, false
|
||||
}
|
||||
|
||||
return insecure, true
|
||||
}
|
||||
|
||||
// GetDefaultProjectID retrieve the default project ID
|
||||
// from the config. Legacy configs used the name
|
||||
// "organization ID" or "organization" for
|
||||
// this field. It will check the following order:
|
||||
// env, legacy env, active profile, default profile
|
||||
//
|
||||
// If the config is present in one of the above environment the
|
||||
// value (which may be empty) is returned and the boolean is true.
|
||||
// Otherwise the returned value will be empty and the boolean will
|
||||
// be false.
|
||||
func (c *configV2) GetDefaultProjectID() (string, bool) {
|
||||
envValue, _, envExist := getenv(scwDefaultProjectIDEnv, cliOrganizationEnv, terraformOrganizationEnv)
|
||||
activeProfile, _ := c.getActiveProfile()
|
||||
|
||||
var defaultProj string
|
||||
switch {
|
||||
case envExist:
|
||||
defaultProj = envValue
|
||||
case activeProfile != "" && c.Profiles[activeProfile].DefaultProjectID != nil:
|
||||
defaultProj = *c.Profiles[activeProfile].DefaultProjectID
|
||||
case c.DefaultProjectID != nil:
|
||||
defaultProj = *c.DefaultProjectID
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
|
||||
// todo: validate format
|
||||
if defaultProj == "" {
|
||||
logger.Warningf("default project ID is empty")
|
||||
}
|
||||
|
||||
return defaultProj, true
|
||||
}
|
||||
|
||||
// GetDefaultRegion retrieve the default region
|
||||
// from the config. It will check the following order:
|
||||
// env, legacy env, active profile, default profile
|
||||
//
|
||||
// If the config is present in one of the above environment the
|
||||
// value (which may be empty) is returned and the boolean is true.
|
||||
// Otherwise the returned value will be empty and the boolean will
|
||||
// be false.
|
||||
func (c *configV2) GetDefaultRegion() (utils.Region, bool) {
|
||||
envValue, _, envExist := getenv(scwDefaultRegionEnv, cliRegionEnv, terraformRegionEnv)
|
||||
activeProfile, _ := c.getActiveProfile()
|
||||
|
||||
var defaultRegion string
|
||||
switch {
|
||||
case envExist:
|
||||
defaultRegion = v1RegionToV2(envValue)
|
||||
case activeProfile != "" && c.Profiles[activeProfile].DefaultRegion != nil:
|
||||
defaultRegion = *c.Profiles[activeProfile].DefaultRegion
|
||||
case c.DefaultRegion != nil:
|
||||
defaultRegion = *c.DefaultRegion
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
|
||||
// todo: validate format
|
||||
if defaultRegion == "" {
|
||||
logger.Warningf("default region is empty")
|
||||
}
|
||||
|
||||
return utils.Region(defaultRegion), true
|
||||
}
|
||||
|
||||
// GetDefaultZone retrieve the default zone
|
||||
// from the config. It will check the following order:
|
||||
// env, legacy env, active profile, default profile
|
||||
//
|
||||
// If the config is present in one of the above environment the
|
||||
// value (which may be empty) is returned and the boolean is true.
|
||||
// Otherwise the returned value will be empty and the boolean will
|
||||
// be false.
|
||||
func (c *configV2) GetDefaultZone() (utils.Zone, bool) {
|
||||
envValue, _, envExist := getenv(scwDefaultZoneEnv)
|
||||
activeProfile, _ := c.getActiveProfile()
|
||||
|
||||
var defaultZone string
|
||||
switch {
|
||||
case envExist:
|
||||
defaultZone = envValue
|
||||
case activeProfile != "" && c.Profiles[activeProfile].DefaultZone != nil:
|
||||
defaultZone = *c.Profiles[activeProfile].DefaultZone
|
||||
case c.DefaultZone != nil:
|
||||
defaultZone = *c.DefaultZone
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
|
||||
// todo: validate format
|
||||
if defaultZone == "" {
|
||||
logger.Warningf("default zone is empty")
|
||||
}
|
||||
|
||||
return utils.Zone(defaultZone), true
|
||||
}
|
||||
|
||||
func getenv(upToDateKey string, deprecatedKeys ...string) (string, string, bool) {
|
||||
value, exist := os.LookupEnv(upToDateKey)
|
||||
if exist {
|
||||
logger.Infof("reading value from %s", upToDateKey)
|
||||
return value, upToDateKey, true
|
||||
}
|
||||
|
||||
for _, key := range deprecatedKeys {
|
||||
value, exist := os.LookupEnv(key)
|
||||
if exist {
|
||||
logger.Infof("reading value from %s", key)
|
||||
logger.Warningf("%s is deprecated, please use %s instead", key, upToDateKey)
|
||||
return value, key, true
|
||||
}
|
||||
}
|
||||
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
const (
|
||||
v1RegionFrPar = "par1"
|
||||
v1RegionNlAms = "ams1"
|
||||
)
|
||||
|
||||
// configV1 is a Scaleway CLI configuration file
|
||||
type configV1 struct {
|
||||
// Organization is the identifier of the Scaleway organization
|
||||
Organization string `json:"organization"`
|
||||
|
||||
// Token is the authentication token for the Scaleway organization
|
||||
Token string `json:"token"`
|
||||
|
||||
// Version is the actual version of scw CLI
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
func unmarshalConfV1(content []byte) (*configV1, error) {
|
||||
var config configV1
|
||||
err := json.Unmarshal(content, &config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &config, err
|
||||
}
|
||||
|
||||
func (v1 *configV1) toV2() *configV2 {
|
||||
return &configV2{
|
||||
profile: profile{
|
||||
DefaultProjectID: &v1.Organization,
|
||||
SecretKey: &v1.Token,
|
||||
// ignore v1 version
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func v1RegionToV2(region string) string {
|
||||
switch region {
|
||||
case v1RegionFrPar:
|
||||
logger.Warningf("par1 is a deprecated name for region, use fr-par instead")
|
||||
return "fr-par"
|
||||
case v1RegionNlAms:
|
||||
logger.Warningf("ams1 is a deprecated name for region, use nl-ams instead")
|
||||
return "nl-ams"
|
||||
default:
|
||||
return region
|
||||
}
|
||||
}
|
104
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/load.go
generated
vendored
Normal file
104
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/load.go
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
package scwconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
documentationLink = "https://github.com/scaleway/scaleway-sdk-go/blob/master/scwconfig/README.md"
|
||||
)
|
||||
|
||||
// LoadWithProfile call Load() and set withProfile with the profile name.
|
||||
func LoadWithProfile(profileName string) (Config, error) {
|
||||
config, err := Load()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v2Loaded := config.(*configV2)
|
||||
v2Loaded.withProfile = profileName
|
||||
return v2Loaded.catchInvalidProfile()
|
||||
}
|
||||
|
||||
// Load config in the following order:
|
||||
// - config file from SCW_CONFIG_PATH (V2 or V1)
|
||||
// - config file V2
|
||||
// - config file V1
|
||||
// When the latest is found it migrates the V1 config
|
||||
// to a V2 config following the V2 config path.
|
||||
func Load() (Config, error) {
|
||||
// STEP 1: try to load config file from SCW_CONFIG_PATH
|
||||
configPath := os.Getenv(scwConfigPathEnv)
|
||||
if configPath != "" {
|
||||
content, err := ioutil.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read config file %s: %s", scwConfigPathEnv, err)
|
||||
}
|
||||
confV1, err := unmarshalConfV1(content)
|
||||
if err == nil {
|
||||
// do not migrate automatically when using SCW_CONFIG_PATH
|
||||
logger.Warningf("loaded config V1 from %s: config V1 is deprecated, please switch your config file to the V2: %s", configPath, documentationLink)
|
||||
return confV1.toV2().catchInvalidProfile()
|
||||
}
|
||||
confV2, err := unmarshalConfV2(content)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("content of config file %s is invalid: %s", configPath, err)
|
||||
}
|
||||
|
||||
logger.Infof("successfully loaded config V2 from %s", configPath)
|
||||
return confV2.catchInvalidProfile()
|
||||
}
|
||||
|
||||
// STEP 2: try to load config file V2
|
||||
v2Path, v2PathOk := GetConfigV2FilePath()
|
||||
if v2PathOk && fileExist(v2Path) {
|
||||
file, err := ioutil.ReadFile(v2Path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read config file: %s", err)
|
||||
}
|
||||
|
||||
confV2, err := unmarshalConfV2(file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("content of config file %s is invalid: %s", v2Path, err)
|
||||
}
|
||||
|
||||
logger.Infof("successfully loaded config V2 from %s", v2Path)
|
||||
return confV2.catchInvalidProfile()
|
||||
}
|
||||
|
||||
// STEP 3: try to load config file V1
|
||||
logger.Debugf("no config V2 found, fall back to config V1")
|
||||
v1Path, v1PathOk := GetConfigV1FilePath()
|
||||
if !v1PathOk {
|
||||
logger.Infof("config file not found: no home directory")
|
||||
return (&configV2{}).catchInvalidProfile()
|
||||
}
|
||||
file, err := ioutil.ReadFile(v1Path)
|
||||
if err != nil {
|
||||
logger.Infof("cannot read config file: %s", err)
|
||||
return (&configV2{}).catchInvalidProfile() // ignore if file doesn't exist
|
||||
}
|
||||
confV1, err := unmarshalConfV1(file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("content of config file %s is invalid json: %s", v1Path, err)
|
||||
}
|
||||
|
||||
// STEP 4: migrate V1 config to V2 config file
|
||||
if v2PathOk {
|
||||
err = migrateV1toV2(confV1, v2Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return confV1.toV2().catchInvalidProfile()
|
||||
}
|
||||
|
||||
func fileExist(name string) bool {
|
||||
_, err := os.Stat(name)
|
||||
return err == nil
|
||||
}
|
47
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/migrate.go
generated
vendored
Normal file
47
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/migrate.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
package scwconfig
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/logger"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultConfigPermission = 0600
|
||||
)
|
||||
|
||||
// migrateV1toV2 converts the V1 config to V2 config and save it in the target path
|
||||
// use config.Save() when the method is public
|
||||
func migrateV1toV2(configV1 *configV1, targetPath string) error {
|
||||
// STEP 0: get absolute target path
|
||||
|
||||
targetPath = filepath.Clean(targetPath)
|
||||
|
||||
// STEP 1: create dir
|
||||
err := os.MkdirAll(filepath.Dir(targetPath), 0700)
|
||||
if err != nil {
|
||||
logger.Debugf("mkdir did not work on %s: %s", filepath.Dir(targetPath), err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// STEP 2: marshal yaml config
|
||||
newConfig := configV1.toV2()
|
||||
file, err := yaml.Marshal(newConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// STEP 3: save config
|
||||
err = ioutil.WriteFile(targetPath, file, defaultConfigPermission)
|
||||
if err != nil {
|
||||
logger.Debugf("cannot write file %s: %s", targetPath, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// STEP 4: log success
|
||||
logger.Infof("config successfully migrated to %s", targetPath)
|
||||
return nil
|
||||
}
|
71
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/path.go
generated
vendored
Normal file
71
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/scwconfig/path.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
package scwconfig
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
unixHomeDirEnv = "HOME"
|
||||
windowsHomeDirEnv = "USERPROFILE"
|
||||
xdgConfigDirEnv = "XDG_CONFIG_HOME"
|
||||
|
||||
defaultConfigFileName = "config.yaml"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoHomeDir errors when no user directory is found
|
||||
ErrNoHomeDir = errors.New("user home directory not found")
|
||||
)
|
||||
|
||||
func inConfigFile() string {
|
||||
v2path, exist := GetConfigV2FilePath()
|
||||
if exist {
|
||||
return "in config file " + v2path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetConfigV2FilePath returns the path to the Scaleway CLI config file
|
||||
func GetConfigV2FilePath() (string, bool) {
|
||||
configDir, err := GetScwConfigDir()
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
return filepath.Join(configDir, defaultConfigFileName), true
|
||||
}
|
||||
|
||||
// GetConfigV1FilePath returns the path to the Scaleway CLI config file
|
||||
func GetConfigV1FilePath() (string, bool) {
|
||||
path, err := GetHomeDir()
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
return filepath.Join(path, ".scwrc"), true
|
||||
}
|
||||
|
||||
// GetScwConfigDir returns the path to scw config folder
|
||||
func GetScwConfigDir() (string, error) {
|
||||
if xdgPath := os.Getenv(xdgConfigDirEnv); xdgPath != "" {
|
||||
return filepath.Join(xdgPath, "scw"), nil
|
||||
}
|
||||
|
||||
homeDir, err := GetHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(homeDir, ".config", "scw"), nil
|
||||
}
|
||||
|
||||
// GetHomeDir returns the path to your home directory
|
||||
func GetHomeDir() (string, error) {
|
||||
switch {
|
||||
case os.Getenv(unixHomeDirEnv) != "":
|
||||
return os.Getenv(unixHomeDirEnv), nil
|
||||
case os.Getenv(windowsHomeDirEnv) != "":
|
||||
return os.Getenv(windowsHomeDirEnv), nil
|
||||
default:
|
||||
return "", ErrNoHomeDir
|
||||
}
|
||||
}
|
158
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/convert.go
generated
vendored
Normal file
158
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/convert.go
generated
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
package utils
|
||||
|
||||
import "time"
|
||||
|
||||
// String returns a pointer to the string value passed in.
|
||||
func String(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
// StringSlice converts a slice of string values into a slice of
|
||||
// string pointers
|
||||
func StringSlice(src []string) []*string {
|
||||
dst := make([]*string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Strings returns a pointer to the []string value passed in.
|
||||
func Strings(v []string) *[]string {
|
||||
return &v
|
||||
}
|
||||
|
||||
// StringsSlice converts a slice of []string values into a slice of
|
||||
// []string pointers
|
||||
func StringsSlice(src [][]string) []*[]string {
|
||||
dst := make([]*[]string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Bytes returns a pointer to the []byte value passed in.
|
||||
func Bytes(v []byte) *[]byte {
|
||||
return &v
|
||||
}
|
||||
|
||||
// BytesSlice converts a slice of []byte values into a slice of
|
||||
// []byte pointers
|
||||
func BytesSlice(src [][]byte) []*[]byte {
|
||||
dst := make([]*[]byte, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Bool returns a pointer to the bool value passed in.
|
||||
func Bool(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
// BoolSlice converts a slice of bool values into a slice of
|
||||
// bool pointers
|
||||
func BoolSlice(src []bool) []*bool {
|
||||
dst := make([]*bool, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32 returns a pointer to the int32 value passed in.
|
||||
func Int32(v int32) *int32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int32Slice converts a slice of int32 values into a slice of
|
||||
// int32 pointers
|
||||
func Int32Slice(src []int32) []*int32 {
|
||||
dst := make([]*int32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64 returns a pointer to the int64 value passed in.
|
||||
func Int64(v int64) *int64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int64Slice converts a slice of int64 values into a slice of
|
||||
// int64 pointers
|
||||
func Int64Slice(src []int64) []*int64 {
|
||||
dst := make([]*int64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint32 returns a pointer to the uint32 value passed in.
|
||||
func Uint32(v uint32) *uint32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Uint32Slice converts a slice of uint32 values into a slice of
|
||||
// uint32 pointers
|
||||
func Uint32Slice(src []uint32) []*uint32 {
|
||||
dst := make([]*uint32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint64 returns a pointer to the uint64 value passed in.
|
||||
func Uint64(v uint64) *uint64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Uint64Slice converts a slice of uint64 values into a slice of
|
||||
// uint64 pointers
|
||||
func Uint64Slice(src []uint64) []*uint64 {
|
||||
dst := make([]*uint64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32 returns a pointer to the float32 value passed in.
|
||||
func Float32(v float32) *float32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Float32Slice converts a slice of float32 values into a slice of
|
||||
// float32 pointers
|
||||
func Float32Slice(src []float32) []*float32 {
|
||||
dst := make([]*float32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64 returns a pointer to the float64 value passed in.
|
||||
func Float64(v float64) *float64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Float64Slice converts a slice of float64 values into a slice of
|
||||
// float64 pointers
|
||||
func Float64Slice(src []float64) []*float64 {
|
||||
dst := make([]*float64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Duration returns a pointer to the Duration value passed in.
|
||||
func Duration(v time.Duration) *time.Duration {
|
||||
return &v
|
||||
}
|
15
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/file.go
generated
vendored
Normal file
15
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/file.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
package utils
|
||||
|
||||
import "io"
|
||||
|
||||
// File is the structure used to receive / send a file from / to the API
|
||||
type File struct {
|
||||
// Name of the file
|
||||
Name string `json:"name"`
|
||||
|
||||
// ContentType used in the HTTP header `Content-Type`
|
||||
ContentType string `json:"content_type"`
|
||||
|
||||
// Content of the file
|
||||
Content io.Reader `json:"content"`
|
||||
}
|
155
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/locality.go
generated
vendored
Normal file
155
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/locality.go
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/scaleway/scaleway-sdk-go/logger"
|
||||
)
|
||||
|
||||
// Zone is an availability zone
|
||||
type Zone string
|
||||
|
||||
const (
|
||||
// ZoneFrPar1 represents the fr-par-1 zone
|
||||
ZoneFrPar1 = Zone("fr-par-1")
|
||||
// ZoneFrPar2 represents the fr-par-2 zone
|
||||
ZoneFrPar2 = Zone("fr-par-2")
|
||||
// ZoneNlAms1 represents the nl-ams-1 zone
|
||||
ZoneNlAms1 = Zone("nl-ams-1")
|
||||
)
|
||||
|
||||
var (
|
||||
// AllZones is an array that list all zones
|
||||
AllZones = []Zone{
|
||||
ZoneFrPar1,
|
||||
ZoneFrPar2,
|
||||
ZoneNlAms1,
|
||||
}
|
||||
)
|
||||
|
||||
// Exists checks whether a zone exists
|
||||
func (zone *Zone) Exists() bool {
|
||||
for _, z := range AllZones {
|
||||
if z == *zone {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Region is a geographical location
|
||||
type Region string
|
||||
|
||||
const (
|
||||
// RegionFrPar represents the fr-par region
|
||||
RegionFrPar = Region("fr-par")
|
||||
// RegionNlAms represents the nl-ams region
|
||||
RegionNlAms = Region("nl-ams")
|
||||
)
|
||||
|
||||
var (
|
||||
// AllRegions is an array that list all regions
|
||||
AllRegions = []Region{
|
||||
RegionFrPar,
|
||||
RegionNlAms,
|
||||
}
|
||||
)
|
||||
|
||||
// Exists checks whether a region exists
|
||||
func (region *Region) Exists() bool {
|
||||
for _, r := range AllRegions {
|
||||
if r == *region {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetZones is a function that returns the zones for the specified region
|
||||
func (region Region) GetZones() []Zone {
|
||||
switch region {
|
||||
case RegionFrPar:
|
||||
return []Zone{ZoneFrPar1, ZoneFrPar2}
|
||||
case RegionNlAms:
|
||||
return []Zone{ZoneNlAms1}
|
||||
default:
|
||||
return []Zone{}
|
||||
}
|
||||
}
|
||||
|
||||
// ParseZone parse a string value into a Zone object
|
||||
func ParseZone(zone string) (Zone, error) {
|
||||
switch zone {
|
||||
case "par1":
|
||||
// would be triggered by API market place
|
||||
// logger.Warningf("par1 is a deprecated name for zone, use fr-par-1 instead")
|
||||
return ZoneFrPar1, nil
|
||||
case "ams1":
|
||||
// would be triggered by API market place
|
||||
// logger.Warningf("ams1 is a deprecated name for zone, use nl-ams-1 instead")
|
||||
return ZoneNlAms1, nil
|
||||
default:
|
||||
newZone := Zone(zone)
|
||||
if !newZone.Exists() {
|
||||
logger.Warningf("%s is an unknown zone", newZone)
|
||||
}
|
||||
return newZone, nil
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the Unmarshaler interface for a Zone.
|
||||
// this to call ParseZone on the string input and return the correct Zone object.
|
||||
func (zone *Zone) UnmarshalJSON(input []byte) error {
|
||||
|
||||
// parse input value as string
|
||||
var stringValue string
|
||||
err := json.Unmarshal(input, &stringValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// parse string as Zone
|
||||
*zone, err = ParseZone(stringValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseRegion parse a string value into a Zone object
|
||||
func ParseRegion(region string) (Region, error) {
|
||||
switch region {
|
||||
case "par1":
|
||||
// would be triggered by API market place
|
||||
// logger.Warningf("par1 is a deprecated name for region, use fr-par instead")
|
||||
return RegionFrPar, nil
|
||||
case "ams1":
|
||||
// would be triggered by API market place
|
||||
// logger.Warningf("ams1 is a deprecated name for region, use nl-ams instead")
|
||||
return RegionNlAms, nil
|
||||
default:
|
||||
newRegion := Region(region)
|
||||
if !newRegion.Exists() {
|
||||
logger.Warningf("%s is an unknown region", newRegion)
|
||||
}
|
||||
return newRegion, nil
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the Unmarshaler interface for a Region.
|
||||
// this to call ParseRegion on the string input and return the correct Region object.
|
||||
func (region *Region) UnmarshalJSON(input []byte) error {
|
||||
// parse input value as string
|
||||
var stringValue string
|
||||
err := json.Unmarshal(input, &stringValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// parse string as Region
|
||||
*region, err = ParseRegion(stringValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
33
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/money.go
generated
vendored
Normal file
33
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/money.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
package utils
|
||||
|
||||
// Money represents an amount of money with its currency type.
|
||||
type Money struct {
|
||||
// CurrencyCode is the 3-letter currency code defined in ISO 4217.
|
||||
CurrencyCode string `json:"currency_code,omitempty"`
|
||||
|
||||
// Units is the whole units of the amount.
|
||||
// For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
|
||||
Units int64 `json:"units,omitempty"`
|
||||
|
||||
// Nanos is the number of nano (10^-9) units of the amount.
|
||||
// The value must be between -999,999,999 and +999,999,999 inclusive.
|
||||
// If `units` is positive, `nanos` must be positive or zero.
|
||||
// If `units` is zero, `nanos` can be positive, zero, or negative.
|
||||
// If `units` is negative, `nanos` must be negative or zero.
|
||||
// For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
|
||||
Nanos int32 `json:"nanos,omitempty"`
|
||||
}
|
||||
|
||||
// NewMoneyFromFloat conerts a float with currency to a Money object.
|
||||
func NewMoneyFromFloat(value float64, currency string) *Money {
|
||||
return &Money{
|
||||
CurrencyCode: currency,
|
||||
Units: int64(value),
|
||||
Nanos: int32((value - float64(int64(value))) * 1000000000),
|
||||
}
|
||||
}
|
||||
|
||||
// ToFloat converts a Money object to a float.
|
||||
func (m *Money) ToFloat() float64 {
|
||||
return float64(m.Units) + float64(m.Nanos)/1000000000
|
||||
}
|
17
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/service_info.go
generated
vendored
Normal file
17
src/cmd/linuxkit/vendor/github.com/scaleway/scaleway-sdk-go/utils/service_info.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
package utils
|
||||
|
||||
// ServiceInfo contains API metadata
|
||||
// These metadata are only here for debugging. Do not rely on these values
|
||||
type ServiceInfo struct {
|
||||
// Name is the name of the API
|
||||
Name string `json:"name"`
|
||||
|
||||
// Description is a human readable description for the API
|
||||
Description string `json:"description"`
|
||||
|
||||
// Version is the version of the API
|
||||
Version string `json:"version"`
|
||||
|
||||
// DocumentationUrl is the a web url where the documentation of the API can be found
|
||||
DocumentationUrl *string `json:"documentation_url"`
|
||||
}
|
159
src/cmd/linuxkit/vendor/golang.org/x/crypto/blowfish/block.go
generated
vendored
Normal file
159
src/cmd/linuxkit/vendor/golang.org/x/crypto/blowfish/block.go
generated
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blowfish
|
||||
|
||||
// getNextWord returns the next big-endian uint32 value from the byte slice
|
||||
// at the given position in a circular manner, updating the position.
|
||||
func getNextWord(b []byte, pos *int) uint32 {
|
||||
var w uint32
|
||||
j := *pos
|
||||
for i := 0; i < 4; i++ {
|
||||
w = w<<8 | uint32(b[j])
|
||||
j++
|
||||
if j >= len(b) {
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
*pos = j
|
||||
return w
|
||||
}
|
||||
|
||||
// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
|
||||
// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
|
||||
// pi and substitution tables for calls to Encrypt. This is used, primarily,
|
||||
// by the bcrypt package to reuse the Blowfish key schedule during its
|
||||
// set up. It's unlikely that you need to use this directly.
|
||||
func ExpandKey(key []byte, c *Cipher) {
|
||||
j := 0
|
||||
for i := 0; i < 18; i++ {
|
||||
// Using inlined getNextWord for performance.
|
||||
var d uint32
|
||||
for k := 0; k < 4; k++ {
|
||||
d = d<<8 | uint32(key[j])
|
||||
j++
|
||||
if j >= len(key) {
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
c.p[i] ^= d
|
||||
}
|
||||
|
||||
var l, r uint32
|
||||
for i := 0; i < 18; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.p[i], c.p[i+1] = l, r
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s0[i], c.s0[i+1] = l, r
|
||||
}
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s1[i], c.s1[i+1] = l, r
|
||||
}
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s2[i], c.s2[i+1] = l, r
|
||||
}
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s3[i], c.s3[i+1] = l, r
|
||||
}
|
||||
}
|
||||
|
||||
// This is similar to ExpandKey, but folds the salt during the key
|
||||
// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
|
||||
// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
|
||||
// and specializing it here is useful.
|
||||
func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
|
||||
j := 0
|
||||
for i := 0; i < 18; i++ {
|
||||
c.p[i] ^= getNextWord(key, &j)
|
||||
}
|
||||
|
||||
j = 0
|
||||
var l, r uint32
|
||||
for i := 0; i < 18; i += 2 {
|
||||
l ^= getNextWord(salt, &j)
|
||||
r ^= getNextWord(salt, &j)
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.p[i], c.p[i+1] = l, r
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l ^= getNextWord(salt, &j)
|
||||
r ^= getNextWord(salt, &j)
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s0[i], c.s0[i+1] = l, r
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l ^= getNextWord(salt, &j)
|
||||
r ^= getNextWord(salt, &j)
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s1[i], c.s1[i+1] = l, r
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l ^= getNextWord(salt, &j)
|
||||
r ^= getNextWord(salt, &j)
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s2[i], c.s2[i+1] = l, r
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l ^= getNextWord(salt, &j)
|
||||
r ^= getNextWord(salt, &j)
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s3[i], c.s3[i+1] = l, r
|
||||
}
|
||||
}
|
||||
|
||||
func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
||||
xl, xr := l, r
|
||||
xl ^= c.p[0]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
|
||||
xr ^= c.p[17]
|
||||
return xr, xl
|
||||
}
|
||||
|
||||
func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
||||
xl, xr := l, r
|
||||
xl ^= c.p[17]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
|
||||
xr ^= c.p[0]
|
||||
return xr, xl
|
||||
}
|
91
src/cmd/linuxkit/vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
Normal file
91
src/cmd/linuxkit/vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
|
||||
package blowfish // import "golang.org/x/crypto/blowfish"
|
||||
|
||||
// The code is a port of Bruce Schneier's C implementation.
|
||||
// See https://www.schneier.com/blowfish.html.
|
||||
|
||||
import "strconv"
|
||||
|
||||
// The Blowfish block size in bytes.
|
||||
const BlockSize = 8
|
||||
|
||||
// A Cipher is an instance of Blowfish encryption using a particular key.
|
||||
type Cipher struct {
|
||||
p [18]uint32
|
||||
s0, s1, s2, s3 [256]uint32
|
||||
}
|
||||
|
||||
type KeySizeError int
|
||||
|
||||
func (k KeySizeError) Error() string {
|
||||
return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
|
||||
}
|
||||
|
||||
// NewCipher creates and returns a Cipher.
|
||||
// The key argument should be the Blowfish key, from 1 to 56 bytes.
|
||||
func NewCipher(key []byte) (*Cipher, error) {
|
||||
var result Cipher
|
||||
if k := len(key); k < 1 || k > 56 {
|
||||
return nil, KeySizeError(k)
|
||||
}
|
||||
initCipher(&result)
|
||||
ExpandKey(key, &result)
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
|
||||
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
|
||||
// sufficient and desirable. For bcrypt compatibility, the key can be over 56
|
||||
// bytes.
|
||||
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
|
||||
if len(salt) == 0 {
|
||||
return NewCipher(key)
|
||||
}
|
||||
var result Cipher
|
||||
if k := len(key); k < 1 {
|
||||
return nil, KeySizeError(k)
|
||||
}
|
||||
initCipher(&result)
|
||||
expandKeyWithSalt(key, salt, &result)
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// BlockSize returns the Blowfish block size, 8 bytes.
|
||||
// It is necessary to satisfy the Block interface in the
|
||||
// package "crypto/cipher".
|
||||
func (c *Cipher) BlockSize() int { return BlockSize }
|
||||
|
||||
// Encrypt encrypts the 8-byte buffer src using the key k
|
||||
// and stores the result in dst.
|
||||
// Note that for amounts of data larger than a block,
|
||||
// it is not safe to just call Encrypt on successive blocks;
|
||||
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
||||
func (c *Cipher) Encrypt(dst, src []byte) {
|
||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
||||
l, r = encryptBlock(l, r, c)
|
||||
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
||||
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
||||
}
|
||||
|
||||
// Decrypt decrypts the 8-byte buffer src using the key k
|
||||
// and stores the result in dst.
|
||||
func (c *Cipher) Decrypt(dst, src []byte) {
|
||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
||||
l, r = decryptBlock(l, r, c)
|
||||
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
||||
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
||||
}
|
||||
|
||||
func initCipher(c *Cipher) {
|
||||
copy(c.p[0:], p[0:])
|
||||
copy(c.s0[0:], s0[0:])
|
||||
copy(c.s1[0:], s1[0:])
|
||||
copy(c.s2[0:], s2[0:])
|
||||
copy(c.s3[0:], s3[0:])
|
||||
}
|
199
src/cmd/linuxkit/vendor/golang.org/x/crypto/blowfish/const.go
generated
vendored
Normal file
199
src/cmd/linuxkit/vendor/golang.org/x/crypto/blowfish/const.go
generated
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The startup permutation array and substitution boxes.
|
||||
// They are the hexadecimal digits of PI; see:
|
||||
// https://www.schneier.com/code/constants.txt.
|
||||
|
||||
package blowfish
|
||||
|
||||
var s0 = [256]uint32{
|
||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
|
||||
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
|
||||
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
|
||||
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
|
||||
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
|
||||
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
|
||||
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
|
||||
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
|
||||
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
|
||||
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
|
||||
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
|
||||
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
|
||||
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
|
||||
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
|
||||
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
|
||||
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
|
||||
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
|
||||
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
|
||||
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
|
||||
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
|
||||
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
|
||||
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
|
||||
}
|
||||
|
||||
var s1 = [256]uint32{
|
||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
|
||||
0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
|
||||
0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
|
||||
0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
|
||||
0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
|
||||
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
|
||||
0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
|
||||
0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
|
||||
0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
|
||||
0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
|
||||
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
|
||||
0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
|
||||
0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
|
||||
0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
|
||||
0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
|
||||
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
|
||||
0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
|
||||
0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
|
||||
0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
|
||||
0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
|
||||
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
|
||||
0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
|
||||
}
|
||||
|
||||
var s2 = [256]uint32{
|
||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
|
||||
0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
|
||||
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
|
||||
0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
|
||||
0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
|
||||
0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
|
||||
0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
|
||||
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
|
||||
0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
|
||||
0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
|
||||
0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
|
||||
0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
|
||||
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
|
||||
0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
|
||||
0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
|
||||
0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
|
||||
0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
|
||||
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
|
||||
0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
|
||||
0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
|
||||
0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
|
||||
0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
|
||||
}
|
||||
|
||||
var s3 = [256]uint32{
|
||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
|
||||
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
|
||||
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
|
||||
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
|
||||
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
|
||||
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
|
||||
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
|
||||
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
|
||||
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
|
||||
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
|
||||
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
|
||||
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
|
||||
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
|
||||
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
|
||||
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
|
||||
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
|
||||
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
|
||||
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
|
||||
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
|
||||
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
|
||||
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
|
||||
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
|
||||
}
|
||||
|
||||
var p = [18]uint32{
|
||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
|
||||
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
|
||||
}
|
Loading…
Reference in New Issue
Block a user