mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-22 02:21:34 +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]`
|
- [Google Cloud](docs/platform-gcp.md) `[x86_64]`
|
||||||
- [Microsoft Azure](docs/platform-azure.md) `[x86_64]`
|
- [Microsoft Azure](docs/platform-azure.md) `[x86_64]`
|
||||||
- [OpenStack](docs/platform-openstack.md) `[x86_64]`
|
- [OpenStack](docs/platform-openstack.md) `[x86_64]`
|
||||||
|
- [Scaleway](docs/platform-scaleway.md) `[x86_64]`
|
||||||
- Baremetal:
|
- Baremetal:
|
||||||
- [packet.net](docs/platform-packet.md) `[x86_64, arm64]`
|
- [packet.net](docs/platform-packet.md) `[x86_64, arm64]`
|
||||||
- [Raspberry Pi Model 3b](docs/platform-rpi3.md) `[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)
|
This is a quick guide to run LinuxKit on Scaleway (only VPS x86_64 for now)
|
||||||
|
|
||||||
## Setup
|
## 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.
|
You must create a Scaleway Secret Key (available ine the [Scaleway Console](https://console.scaleway.com/account/credentials)) first.
|
||||||
The `-token` flag of the `linuxkit push scaleway` and `linuxkit run scaleway` can also be used.
|
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_TARGET_REGION` is used to set the region (there is also the `-region` flag)
|
|
||||||
|
|
||||||
|
The environment variable `SCW_DEFAULT_ZONE` is used to set the zone (there is also the `-zone` flag)
|
||||||
|
|
||||||
## Build an image
|
## 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 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
|
### Push process
|
||||||
|
|
||||||
Building a Scaleway image have a special process. Basically:
|
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
|
* Copy the ISO image on this instance
|
||||||
* Use `dd` to write the image on the additional volume (`/dev/vdb` by default)
|
* 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
|
* Terminate the instance, create a snapshot, and create an image from the snapshot
|
||||||
|
@ -20,11 +20,12 @@ func pushScaleway(args []string) {
|
|||||||
flags.PrintDefaults()
|
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")
|
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")
|
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.")
|
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")
|
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")
|
noCleanFlag := flags.Bool("no-clean", false, "Do not remove temporary instance and volumes")
|
||||||
|
|
||||||
if err := flags.Parse(args); err != nil {
|
if err := flags.Parse(args); err != nil {
|
||||||
@ -40,11 +41,12 @@ func pushScaleway(args []string) {
|
|||||||
path := remArgs[0]
|
path := remArgs[0]
|
||||||
|
|
||||||
name := getStringValue(scalewayNameVar, *nameFlag, "")
|
name := getStringValue(scalewayNameVar, *nameFlag, "")
|
||||||
token := getStringValue(tokenVar, *tokenFlag, "")
|
secretKey := getStringValue(secretKeyVar, *secretKeyFlag, "")
|
||||||
sshKeyFile := getStringValue(sshKeyVar, *sshKeyFlag, "")
|
sshKeyFile := getStringValue(sshKeyVar, *sshKeyFlag, "")
|
||||||
instanceID := getStringValue(instanceIDVar, *instanceIDFlag, "")
|
instanceID := getStringValue(instanceIDVar, *instanceIDFlag, "")
|
||||||
deviceName := getStringValue(deviceNameVar, *deviceNameFlag, "")
|
deviceName := getStringValue(deviceNameVar, *deviceNameFlag, "")
|
||||||
region := getStringValue(regionVar, *regionFlag, defaultScalewayRegion)
|
zone := getStringValue(zoneVar, *zoneFlag, defaultScalewayZone)
|
||||||
|
projectID := getStringValue(projectIDVar, *projectIDFlag, "")
|
||||||
|
|
||||||
const suffix = ".iso"
|
const suffix = ".iso"
|
||||||
if name == "" {
|
if name == "" {
|
||||||
@ -52,7 +54,7 @@ func pushScaleway(args []string) {
|
|||||||
name = filepath.Base(name)
|
name = filepath.Base(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := NewScalewayClient(token, region)
|
client, err := NewScalewayClient(secretKey, zone, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to connect to Scaleway: %v", err)
|
log.Fatalf("Unable to connect to Scaleway: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultScalewayInstanceType = "VC1S"
|
defaultScalewayInstanceType = "DEV1-S"
|
||||||
defaultScalewayRegion = "par1"
|
defaultScalewayZone = "par1"
|
||||||
|
|
||||||
scalewayNameVar = "SCW_IMAGE_NAME" // non-standard
|
scalewayNameVar = "SCW_IMAGE_NAME" // non-standard
|
||||||
tokenVar = "SCW_TOKEN" // non-standard
|
secretKeyVar = "SCW_SECRET_KEY" // non-standard
|
||||||
sshKeyVar = "SCW_SSH_KEY_FILE" // non-standard
|
sshKeyVar = "SCW_SSH_KEY_FILE" // non-standard
|
||||||
instanceIDVar = "SCW_INSTANCE_ID" // non-standard
|
instanceIDVar = "SCW_INSTANCE_ID" // non-standard
|
||||||
deviceNameVar = "SCW_DEVICE_NAME" // 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
|
instanceTypeVar = "SCW_RUN_TYPE" // non-standard
|
||||||
)
|
)
|
||||||
@ -35,8 +36,9 @@ func runScaleway(args []string) {
|
|||||||
}
|
}
|
||||||
instanceTypeFlag := flags.String("instance-type", defaultScalewayInstanceType, "Scaleway instance type")
|
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")
|
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")
|
secretKeyFlag := flags.String("secret-key", "", "Secret Key to connect to Scaleway API")
|
||||||
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")
|
||||||
cleanFlag := flags.Bool("clean", false, "Remove instance")
|
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")
|
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)
|
instanceType := getStringValue(instanceTypeVar, *instanceTypeFlag, defaultScalewayInstanceType)
|
||||||
instanceName := getStringValue("", *instanceNameFlag, name)
|
instanceName := getStringValue("", *instanceNameFlag, name)
|
||||||
token := getStringValue(tokenVar, *tokenFlag, "")
|
secretKey := getStringValue(secretKeyVar, *secretKeyFlag, "")
|
||||||
region := getStringValue(regionVar, *regionFlag, defaultScalewayRegion)
|
zone := getStringValue(scwZoneVar, *zoneFlag, defaultScalewayZone)
|
||||||
|
projectID := getStringValue(projectIDVar, *projectIDFlag, "")
|
||||||
|
|
||||||
client, err := NewScalewayClient(token, region)
|
client, err := NewScalewayClient(secretKey, zone, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to connect to Scaleway: %v", err)
|
log.Fatalf("Unable to connect to Scaleway: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -11,143 +10,189 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ScaleFT/sshkeys"
|
||||||
gotty "github.com/moul/gotty-client"
|
gotty "github.com/moul/gotty-client"
|
||||||
scw "github.com/scaleway/go-scaleway"
|
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
|
||||||
"github.com/scaleway/go-scaleway/logger"
|
"github.com/scaleway/scaleway-sdk-go/api/marketplace/v1"
|
||||||
"github.com/scaleway/go-scaleway/types"
|
"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"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/crypto/ssh"
|
"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
|
// ScalewayClient contains state required for communication with Scaleway as well as the instance
|
||||||
type ScalewayClient struct {
|
type ScalewayClient struct {
|
||||||
api *scw.ScalewayAPI
|
instanceAPI *instance.API
|
||||||
fileName string
|
marketplaceAPI *marketplace.API
|
||||||
region string
|
fileName string
|
||||||
sshConfig *ssh.ClientConfig
|
zone string
|
||||||
}
|
sshConfig *ssh.ClientConfig
|
||||||
|
secretKey string
|
||||||
// ScalewayConfig contains required field to read scaleway config file
|
|
||||||
type ScalewayConfig struct {
|
|
||||||
Organization string `json:"organization"`
|
|
||||||
Token string `json:"token"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewScalewayClient creates a new scaleway client
|
// 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")
|
log.Debugf("Connecting to Scaleway")
|
||||||
organization := ""
|
if secretKey == "" {
|
||||||
if token == "" {
|
config, err := scwconfig.Load()
|
||||||
log.Debugf("Using .scwrc file to get token")
|
if err != nil {
|
||||||
homeDir := os.Getenv("HOME")
|
return nil, err
|
||||||
if homeDir == "" {
|
}
|
||||||
homeDir = os.Getenv("USERPROFILE") // Windows support
|
|
||||||
}
|
scwClient, err = scw.NewClient(
|
||||||
if homeDir == "" {
|
scw.WithConfig(config),
|
||||||
return nil, fmt.Errorf("Home directory not found")
|
)
|
||||||
}
|
if err != nil {
|
||||||
swrcPath := filepath.Join(homeDir, ".scwrc")
|
return nil, err
|
||||||
|
}
|
||||||
file, err := ioutil.ReadFile(swrcPath)
|
} else {
|
||||||
if err != nil {
|
scwZone, err := utils.ParseZone(zone)
|
||||||
return nil, fmt.Errorf("Error reading Scaleway config file: %v", err)
|
if err != nil {
|
||||||
}
|
return nil, err
|
||||||
|
}
|
||||||
var scalewayConfig ScalewayConfig
|
|
||||||
err = json.Unmarshal(file, &scalewayConfig)
|
scwClient, err = scw.NewClient(
|
||||||
if err != nil {
|
scw.WithAuth("", secretKey),
|
||||||
return nil, fmt.Errorf("Error during unmarshal of Scaleway config file: %v", err)
|
scw.WithDefaultZone(scwZone),
|
||||||
}
|
scw.WithDefaultProjectID(projectID),
|
||||||
|
)
|
||||||
token = scalewayConfig.Token
|
|
||||||
organization = scalewayConfig.Organization
|
|
||||||
}
|
|
||||||
|
|
||||||
api, err := scw.NewScalewayAPI(organization, token, "", region)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
l := logger.NewDisableLogger()
|
|
||||||
api.Logger = l
|
|
||||||
|
|
||||||
if organization == "" {
|
|
||||||
organisations, err := api.GetOrganization()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
api.Organization = organisations.Organizations[0].ID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceAPI := instance.NewAPI(scwClient)
|
||||||
|
marketplaceAPI := marketplace.NewAPI(scwClient)
|
||||||
|
|
||||||
client := &ScalewayClient{
|
client := &ScalewayClient{
|
||||||
api: api,
|
instanceAPI: instanceAPI,
|
||||||
fileName: "",
|
marketplaceAPI: marketplaceAPI,
|
||||||
region: region,
|
zone: zone,
|
||||||
|
fileName: "",
|
||||||
|
secretKey: secretKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
return client, nil
|
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
|
// CreateInstance create an instance with one additional volume
|
||||||
func (s *ScalewayClient) CreateInstance() (string, error) {
|
func (s *ScalewayClient) CreateInstance() (string, error) {
|
||||||
// get the Ubuntu Xenial image id
|
// 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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
imageID := image.Identifier
|
|
||||||
|
|
||||||
var serverDefinition types.ScalewayServerDefinition
|
createVolumeRequest := &instance.CreateVolumeRequest{
|
||||||
|
Name: "linuxkit-builder-volume",
|
||||||
serverDefinition.Name = "linuxkit-builder"
|
VolumeType: "l_ssd",
|
||||||
serverDefinition.Image = &imageID
|
Size: &defaultVolumeSize,
|
||||||
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"
|
|
||||||
|
|
||||||
log.Debugf("Creating volume on Scaleway")
|
log.Debugf("Creating volume on Scaleway")
|
||||||
volumeID, err := s.api.PostVolume(volumeDefinition)
|
volumeResp, err := s.instanceAPI.CreateVolume(createVolumeRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
serverDefinition.Volumes = make(map[string]string)
|
volumeMap := make(map[string]*instance.VolumeTemplate)
|
||||||
serverDefinition.Volumes["1"] = volumeID
|
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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Created server %s on Scaleway", serverID)
|
attachVolumeRequest := &instance.AttachVolumeRequest{
|
||||||
return serverID, nil
|
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
|
// GetSecondVolumeID returns the ID of the second volume of the server
|
||||||
func (s *ScalewayClient) GetSecondVolumeID(instanceID string) (string, error) {
|
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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
secondVolume, ok := server.Volumes["1"]
|
secondVolume, ok := serverResp.Server.Volumes["1"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", errors.New("No second volume found")
|
return "", errors.New("No second volume found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return secondVolume.Identifier, nil
|
return secondVolume.ID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BootInstanceAndWait boots and wait for instance to be booted
|
// BootInstanceAndWait boots and wait for instance to be booted
|
||||||
func (s *ScalewayClient) BootInstanceAndWait(instanceID string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -156,14 +201,17 @@ func (s *ScalewayClient) BootInstanceAndWait(instanceID string) error {
|
|||||||
|
|
||||||
// code taken from scaleway-cli, could need some changes
|
// code taken from scaleway-cli, could need some changes
|
||||||
promise := make(chan bool)
|
promise := make(chan bool)
|
||||||
var server *types.ScalewayServer
|
var server *instance.Server
|
||||||
var currentState string
|
var currentState instance.ServerState
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(promise)
|
defer close(promise)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
server, err = s.api.GetServer(instanceID)
|
serverResp, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
|
||||||
|
ServerID: instanceID,
|
||||||
|
})
|
||||||
|
server = serverResp.Server
|
||||||
if err != nil {
|
if err != nil {
|
||||||
promise <- false
|
promise <- false
|
||||||
return
|
return
|
||||||
@ -173,20 +221,17 @@ func (s *ScalewayClient) BootInstanceAndWait(instanceID string) error {
|
|||||||
currentState = server.State
|
currentState = server.State
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.State == "running" {
|
if server.State == instance.ServerStateRunning {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if server.State == "stopped" {
|
if server.State == instance.ServerStateStopped {
|
||||||
promise <- false
|
promise <- false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
ip := server.PublicAddress.IP
|
ip := server.PublicIP.Address.String()
|
||||||
if ip == "" && server.EnableIPV6 {
|
|
||||||
ip = fmt.Sprintf("[%s]", server.IPV6.Address)
|
|
||||||
}
|
|
||||||
dest := fmt.Sprintf("%s:22", ip)
|
dest := fmt.Sprintf("%s:22", ip)
|
||||||
for {
|
for {
|
||||||
conn, err := net.Dial("tcp", dest)
|
conn, err := net.Dial("tcp", dest)
|
||||||
@ -232,7 +277,16 @@ func getSSHAuth(sshKeyPath string) (ssh.Signer, error) {
|
|||||||
}
|
}
|
||||||
signer, err := ssh.ParsePrivateKey(buf)
|
signer, err := ssh.ParsePrivateKey(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
return signer, err
|
||||||
}
|
}
|
||||||
@ -242,10 +296,13 @@ func (s *ScalewayClient) CopyImageToInstance(instanceID, path, sshKeyPath string
|
|||||||
_, base := filepath.Split(path)
|
_, base := filepath.Split(path)
|
||||||
s.fileName = base
|
s.fileName = base
|
||||||
|
|
||||||
server, err := s.api.GetServer(instanceID)
|
serverResp, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
|
||||||
|
ServerID: instanceID,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
server := serverResp.Server
|
||||||
|
|
||||||
signer, err := getSSHAuth(sshKeyPath)
|
signer, err := getSSHAuth(sshKeyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -260,7 +317,7 @@ func (s *ScalewayClient) CopyImageToInstance(instanceID, path, sshKeyPath string
|
|||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(), // TODO validate server before?
|
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 {
|
if err != nil {
|
||||||
return err
|
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
|
// WriteImageToVolume does a dd command on the remote instance via ssh
|
||||||
func (s *ScalewayClient) WriteImageToVolume(instanceID, deviceName string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -350,14 +411,12 @@ func (s *ScalewayClient) WriteImageToVolume(instanceID, deviceName string) error
|
|||||||
|
|
||||||
// TerminateInstance terminates the instance and wait for termination
|
// TerminateInstance terminates the instance and wait for termination
|
||||||
func (s *ScalewayClient) TerminateInstance(instanceID string) error {
|
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)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -365,19 +424,24 @@ func (s *ScalewayClient) TerminateInstance(instanceID string) error {
|
|||||||
// code taken from scaleway-cli
|
// code taken from scaleway-cli
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
|
|
||||||
var currentState string
|
var currentState instance.ServerState
|
||||||
|
|
||||||
log.Debugf("Waiting for server to shutdown")
|
log.Debugf("Waiting for server to shutdown")
|
||||||
|
|
||||||
for {
|
for {
|
||||||
server, err = s.api.GetServer(instanceID)
|
serverResp, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
|
||||||
|
ServerID: instanceID,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server := serverResp.Server
|
||||||
|
|
||||||
if currentState != server.State {
|
if currentState != server.State {
|
||||||
currentState = server.State
|
currentState = server.State
|
||||||
}
|
}
|
||||||
if server.State == "stopped" {
|
if server.State == instance.ServerStateStopped {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(1 * time.Second)
|
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
|
// CreateScalewayImage creates the image and delete old image and snapshot if same name
|
||||||
func (s *ScalewayClient) CreateScalewayImage(instanceID, volumeID, name string) error {
|
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 {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oldSnapshot, err := s.api.GetSnapshotID(name)
|
oldSnapshotsResp, err := s.instanceAPI.ListSnapshots(&instance.ListSnapshotsRequest{
|
||||||
|
Name: &name,
|
||||||
|
}, scw.WithAllPages())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err := s.api.DeleteSnapshot(oldSnapshot)
|
for _, oldSnapshot := range oldSnapshotsResp.Snapshots {
|
||||||
if err != nil {
|
log.Debugf("deleting snapshot %s", oldSnapshot.ID)
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteInstanceAndVolumes deletes the instance and the volumes attached
|
// DeleteInstanceAndVolumes deletes the instance and the volumes attached
|
||||||
func (s *ScalewayClient) DeleteInstanceAndVolumes(instanceID string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.api.DeleteServer(instanceID)
|
err = s.instanceAPI.DeleteServer(&instance.DeleteServerRequest{
|
||||||
|
ServerID: instanceID,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, volume := range server.Volumes {
|
for _, volume := range serverResp.Server.Volumes {
|
||||||
err = s.api.DeleteVolume(volume.Identifier)
|
err = s.instanceAPI.DeleteVolume(&instance.DeleteVolumeRequest{
|
||||||
|
VolumeID: volume.ID,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -445,33 +534,38 @@ func (s *ScalewayClient) DeleteInstanceAndVolumes(instanceID string) error {
|
|||||||
// CreateLinuxkitInstance creates an instance with the given linuxkit image
|
// CreateLinuxkitInstance creates an instance with the given linuxkit image
|
||||||
func (s *ScalewayClient) CreateLinuxkitInstance(instanceName, imageName, instanceType string) (string, error) {
|
func (s *ScalewayClient) CreateLinuxkitInstance(instanceName, imageName, instanceType string) (string, error) {
|
||||||
// get the image ID
|
// 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 {
|
if err != nil {
|
||||||
return "", err
|
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
|
log.Debugf("Creating server %s on Scaleway", instanceName)
|
||||||
|
serverResp, err := s.instanceAPI.CreateServer(&instance.CreateServerRequest{
|
||||||
serverDefinition.Name = instanceName
|
Name: instanceName,
|
||||||
serverDefinition.Image = &imageID
|
DynamicIPRequired: true,
|
||||||
serverDefinition.CommercialType = instanceType
|
CommercialType: instanceType,
|
||||||
serverDefinition.BootType = "local"
|
Image: imageID,
|
||||||
|
BootType: instance.ServerBootTypeLocal,
|
||||||
log.Debugf("Creating volume on Scaleway")
|
})
|
||||||
|
|
||||||
log.Debugf("Creating server %s on Scaleway", serverDefinition.Name)
|
|
||||||
serverID, err := s.api.PostServer(serverDefinition)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return serverID, nil
|
return serverResp.Server.ID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BootInstance boots the specified instance, and don't wait
|
// BootInstance boots the specified instance, and don't wait
|
||||||
func (s *ScalewayClient) BootInstance(instanceID string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -481,7 +575,7 @@ func (s *ScalewayClient) BootInstance(instanceID string) error {
|
|||||||
// ConnectSerialPort connects to the serial port of the instance
|
// ConnectSerialPort connects to the serial port of the instance
|
||||||
func (s *ScalewayClient) ConnectSerialPort(instanceID string) error {
|
func (s *ScalewayClient) ConnectSerialPort(instanceID string) error {
|
||||||
var gottyURL string
|
var gottyURL string
|
||||||
switch s.region {
|
switch s.zone {
|
||||||
case "par1":
|
case "par1":
|
||||||
gottyURL = "https://tty-par1.scaleway.com/v2/"
|
gottyURL = "https://tty-par1.scaleway.com/v2/"
|
||||||
case "ams1":
|
case "ams1":
|
||||||
@ -490,7 +584,7 @@ func (s *ScalewayClient) ConnectSerialPort(instanceID string) error {
|
|||||||
return errors.New("Instance have no region")
|
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)
|
log.Debugf("Connection to %s", fullURL)
|
||||||
gottyClient, err := gotty.NewClient(fullURL)
|
gottyClient, err := gotty.NewClient(fullURL)
|
||||||
|
@ -10,6 +10,7 @@ github.com/containerd/containerd v1.1.2
|
|||||||
github.com/containerd/continuity d8fb8589b0e8e85b8c8bbaa8840226d0dfeb7371
|
github.com/containerd/continuity d8fb8589b0e8e85b8c8bbaa8840226d0dfeb7371
|
||||||
github.com/creack/goselect 58854f77ee8d858ce751b0a9bcc5533fef7bfa9e
|
github.com/creack/goselect 58854f77ee8d858ce751b0a9bcc5533fef7bfa9e
|
||||||
github.com/davecgh/go-spew v1.1.0
|
github.com/davecgh/go-spew v1.1.0
|
||||||
|
github.com/dchest/bcrypt_pbkdf 83f37f9c154a678179d11e218bff73ebe5717f99
|
||||||
github.com/dgrijalva/jwt-go 6c8dedd55f8a2e41f605de6d5d66e51ed1f299fc
|
github.com/dgrijalva/jwt-go 6c8dedd55f8a2e41f605de6d5d66e51ed1f299fc
|
||||||
github.com/docker/cli v18.06.0-ce
|
github.com/docker/cli v18.06.0-ce
|
||||||
github.com/docker/distribution 83389a148052d74ac602f5f1d62f86ff2f3c4aa5
|
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/radu-matei/azure-vhd-utils e52754d5569d2a643a7775f72ff2a6cf524f4c25
|
||||||
github.com/renstrom/fuzzysearch 7a8f9a1c4bed53899ecd512daeaf8207cc454156
|
github.com/renstrom/fuzzysearch 7a8f9a1c4bed53899ecd512daeaf8207cc454156
|
||||||
github.com/rn/iso9660wrap baf8d62ad3155152b488d5ff9d4f2b9bb0d6986a
|
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/sirupsen/logrus v1.0.3
|
||||||
github.com/spf13/cobra v0.0.3
|
github.com/spf13/cobra v0.0.3
|
||||||
github.com/spf13/pflag v1.0.1
|
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