Move aci client (#531)

* Add azure-aci client dep

* Use aci client from new repo
This commit is contained in:
Brian Goff
2019-02-25 17:15:25 -08:00
committed by GitHub
parent 1bfffa975e
commit d19e8e5e27
48 changed files with 268 additions and 1495 deletions

19
Gopkg.lock generated
View File

@@ -1184,6 +1184,19 @@
revision = "38ec4ddb06dedbea0a895c4848b248eb38af221b"
version = "v0.10.2"
[[projects]]
digest = "1:9a98ebb3ee9bb59770d26639de8f2c9a65d695daaa1c1957d34de84a6f40c282"
name = "github.com/virtual-kubelet/azure-aci"
packages = [
"client",
"client/aci",
"client/api",
"client/network",
]
pruneopts = "NUT"
revision = "97883416cb6b6d9bafac89a550bd90ea44d509fa"
version = "v0.1.0"
[[projects]]
digest = "1:a707ec1c12a88afc978307bca7f40bde7bd6b6434ceee41f8d7c6985e245dbdb"
name = "github.com/vishvananda/netlink"
@@ -1870,7 +1883,6 @@
"contrib.go.opencensus.io/exporter/ocagent",
"github.com/Azure/azure-sdk-for-go/profiles/preview/preview/servicefabricmesh/mgmt/servicefabricmesh",
"github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch",
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network",
"github.com/Azure/go-autorest/autorest",
"github.com/Azure/go-autorest/autorest/adal",
"github.com/Azure/go-autorest/autorest/azure",
@@ -1895,7 +1907,6 @@
"github.com/cpuguy83/strongerrors",
"github.com/cpuguy83/strongerrors/status",
"github.com/cpuguy83/strongerrors/status/ocstatus",
"github.com/dimchansky/utfbom",
"github.com/docker/docker/api/types/strslice",
"github.com/docker/go-connections/nat",
"github.com/docker/go-connections/sockets",
@@ -1926,6 +1937,10 @@
"github.com/stretchr/testify/assert",
"github.com/stretchr/testify/mock",
"github.com/stretchr/testify/require",
"github.com/virtual-kubelet/azure-aci/client",
"github.com/virtual-kubelet/azure-aci/client/aci",
"github.com/virtual-kubelet/azure-aci/client/api",
"github.com/virtual-kubelet/azure-aci/client/network",
"github.com/vmware/vic/lib/apiservers/engine/backends/cache",
"github.com/vmware/vic/lib/apiservers/engine/errors",
"github.com/vmware/vic/lib/apiservers/engine/proxy",

View File

@@ -45,8 +45,6 @@
name = "github.com/hyperhq/hyper-api"
revision = "18c77d3f9fe0abebb41b45c12f383ecac46f4ff1"
[[constraint]]
name = "github.com/gorilla/mux"
version = "1.6.0"
@@ -155,3 +153,8 @@
[[override]]
name = "github.com/ugorji/go"
revision = "0053ebfd9d0ee06ccefbfe17072021e1d4acebee"
[[constraint]]
name = "github.com/virtual-kubelet/azure-aci"
version = "v0.1.0"

View File

@@ -20,11 +20,11 @@ import (
"time"
"github.com/gorilla/websocket"
client "github.com/virtual-kubelet/azure-aci/client"
"github.com/virtual-kubelet/azure-aci/client/aci"
"github.com/virtual-kubelet/azure-aci/client/network"
"github.com/virtual-kubelet/virtual-kubelet/log"
"github.com/virtual-kubelet/virtual-kubelet/manager"
client "github.com/virtual-kubelet/virtual-kubelet/providers/azure/client"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/aci"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/network"
"github.com/virtual-kubelet/virtual-kubelet/trace"
v1 "k8s.io/api/core/v1"
k8serr "k8s.io/apimachinery/pkg/api/errors"
@@ -783,7 +783,8 @@ func (p *ACIProvider) ExecInContainer(name string, uid types.UID, container stri
terminalSize = <-resize // Receive terminal resize event if resize stream is present
}
xcrsp, err := p.aciClient.LaunchExec(p.resourceGroup, cg.Name, container, cmd[0], terminalSize)
ts := aci.TerminalSizeRequest{Height: int(terminalSize.Height), Width: int(terminalSize.Width)}
xcrsp, err := p.aciClient.LaunchExec(p.resourceGroup, cg.Name, container, cmd[0], ts)
if err != nil {
return err
}

View File

@@ -7,7 +7,7 @@ import (
"net/http/httptest"
"github.com/gorilla/mux"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/aci"
"github.com/virtual-kubelet/azure-aci/client/aci"
)
// ACIMock implements a Azure Container Instance mock server.

View File

@@ -18,10 +18,10 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
azure "github.com/virtual-kubelet/azure-aci/client"
"github.com/virtual-kubelet/azure-aci/client/aci"
"github.com/virtual-kubelet/virtual-kubelet/manager"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/aci"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"

View File

@@ -1,66 +0,0 @@
# A half-baked SDK for Azure in Go
This is a half-baked (ie. only provides what we needed) SDK for Azure in Go.
## Authentication
### Use an authentication file
This SDK also supports authentication with a JSON file containing credentials for the service principal. In the Azure CLI, you can create a service principal and its authentication file with this command:
``` bash
az ad sp create-for-rbac --sdk-auth > mycredentials.json
```
Save this file in a secure location on your system where your code can read it. Set an environment variable with the full path to the file:
``` bash
export AZURE_AUTH_LOCATION=/secure/location/mycredentials.json
```
``` powershell
$env:AZURE_AUTH_LOCATION= "/secure/location/mycredentials.json"
```
The file looks like this, in case you want to create it yourself:
``` json
{
"clientId": "<your service principal client ID>",
"clientSecret": "your service principal client secret",
"subscriptionId": "<your Azure Subsription ID>",
"tenantId": "<your tenant ID>",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}
```
## Log Analytics support
Log Analytics is supported through environment variables:
- `LOG_ANALYTICS_KEY`
- `LOG_ANALYTICS_ID`
You can also specify a file with these values and specify the path to it in the `LOG_ANALYTICS_AUTH_LOCATION`:
``` bash
export LOG_ANALYTICS_AUTH_LOCATION=/secure/location/loganalytics.json
```
``` powershell
$env:LOG_ANALYTICS_AUTH_LOCATION= "/secure/location/loganalytics.json"
```
The file should look like this:
``` json
{
"workspaceID": "<YOUR_LOG_ANALYTICS_WORKSPACE_ID>",
"workspaceKey": "<YOUR_LOG_ANALYTICS_WORKSPACE_KEY>"
}
```

View File

@@ -1,38 +0,0 @@
package aci
import (
"io/ioutil"
"os"
"testing"
)
func TestLogAnalyticsFileParsingSuccess(t *testing.T) {
diagnostics, err := NewContainerGroupDiagnosticsFromFile("../../../../loganalytics.json")
if err != nil {
t.Fatal(err)
}
if diagnostics == nil || diagnostics.LogAnalytics == nil {
t.Fatalf("Unexpected nil diagnostics. Log Analytics file not parsed correctly")
}
if diagnostics.LogAnalytics.WorkspaceID == "" || diagnostics.LogAnalytics.WorkspaceKey == "" {
t.Fatalf("Unexpected empty analytics authentication credentials. Log Analytics file not parsed correctly")
}
}
func TestLogAnalyticsFileParsingFailure(t *testing.T) {
tempFile, err := ioutil.TempFile("", "")
if err != nil {
t.Fatal(err)
}
_, err = NewContainerGroupDiagnosticsFromFile(tempFile.Name())
// Cleaup
tempFile.Close()
os.Remove(tempFile.Name())
if err == nil {
t.Fatalf("Expected parsing an empty Log Analytics auth file to fail, but there were no errors")
}
}

View File

@@ -1,591 +0,0 @@
package aci
import (
"context"
"encoding/base64"
"fmt"
"log"
"os"
"strings"
"testing"
"github.com/google/uuid"
azure "github.com/virtual-kubelet/virtual-kubelet/providers/azure/client"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/resourcegroups"
)
var (
client *Client
location = "westus"
resourceGroup = "virtual-kubelet-tests"
containerGroup = "virtual-kubelet-test-container-group"
subscriptionID string
)
func init() {
//Create a resource group name with uuid.
uid := uuid.New()
resourceGroup += "-" + uid.String()[0:6]
}
// The TestMain function creates a resource group for testing
// and deletes in when it's done.
func TestMain(m *testing.M) {
auth, err := azure.NewAuthenticationFromFile("../../../../credentials.json")
if err != nil {
log.Fatalf("Failed to load Azure authentication file: %v", err)
}
subscriptionID = auth.SubscriptionID
// Check if the resource group exists and create it if not.
rgCli, err := resourcegroups.NewClient(auth, "unit-test")
if err != nil {
log.Fatalf("creating new resourcegroups client failed: %v", err)
}
// Check if the resource group exists.
exists, err := rgCli.ResourceGroupExists(resourceGroup)
if err != nil {
log.Fatalf("checking if resource group exists failed: %v", err)
}
if !exists {
// Create the resource group.
_, err := rgCli.CreateResourceGroup(resourceGroup, resourcegroups.Group{
Location: location,
})
if err != nil {
log.Fatalf("creating resource group failed: %v", err)
}
}
// Run the tests.
merr := m.Run()
// Delete the resource group.
if err := rgCli.DeleteResourceGroup(resourceGroup); err != nil {
log.Printf("Couldn't delete resource group %q: %v", resourceGroup, err)
}
if merr != 0 {
os.Exit(merr)
}
os.Exit(0)
}
func TestNewClient(t *testing.T) {
auth, err := azure.NewAuthenticationFromFile("../../../../credentials.json")
if err != nil {
log.Fatalf("Failed to load Azure authentication file: %v", err)
}
c, err := NewClient(auth, "unit-test")
if err != nil {
t.Fatal(err)
}
client = c
}
func TestCreateContainerGroupFails(t *testing.T) {
_, err := client.CreateContainerGroup(context.Background(), resourceGroup, containerGroup, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
},
},
},
},
})
if err == nil {
t.Fatal("expected create container group to fail with ResourceRequestsNotSpecified, but returned nil")
}
if !strings.Contains(err.Error(), "ResourceRequestsNotSpecified") {
t.Fatalf("expected ResourceRequestsNotSpecified to be in the error message but got: %v", err)
}
}
func TestCreateContainerGroupWithoutResourceLimit(t *testing.T) {
cg, err := client.CreateContainerGroup(context.Background(), resourceGroup, containerGroup, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
},
},
},
},
},
})
if err != nil {
t.Fatal(err)
}
if cg.Name != containerGroup {
t.Fatalf("resource group name is %s, expected %s", cg.Name, containerGroup)
}
if err := client.DeleteContainerGroup(context.Background(), resourceGroup, containerGroup); err != nil {
t.Fatal(err)
}
}
func TestCreateContainerGroup(t *testing.T) {
cg, err := client.CreateContainerGroup(context.Background(), resourceGroup, containerGroup, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
Limits: &ResourceLimits{
CPU: 1,
MemoryInGB: 1,
},
},
},
},
},
},
})
if err != nil {
t.Fatal(err)
}
if cg.Name != containerGroup {
t.Fatalf("resource group name is %s, expected %s", cg.Name, containerGroup)
}
}
func TestCreateContainerGroupWithBadVNetFails(t *testing.T) {
_, err := client.CreateContainerGroup(context.Background(), resourceGroup, containerGroup, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
Limits: &ResourceLimits{
CPU: 1,
MemoryInGB: 1,
},
},
},
},
},
NetworkProfile: &NetworkProfileDefinition{
ID: fmt.Sprintf(
"/subscriptions/%s/resourceGroups/%s/providers"+
"/Microsoft.Network/networkProfiles/%s",
subscriptionID,
resourceGroup,
"badNetworkProfile",
),
},
},
})
if err == nil {
t.Fatal("expected create container group to fail with NetworkProfileNotFound, but returned nil")
}
if !strings.Contains(err.Error(), "NetworkProfileNotFound") {
t.Fatalf("expected NetworkProfileNotFound to be in the error message but got: %v", err)
}
}
func TestGetContainerGroup(t *testing.T) {
cg, err, _ := client.GetContainerGroup(context.Background(), resourceGroup, containerGroup)
if err != nil {
t.Fatal(err)
}
if cg.Name != containerGroup {
t.Fatalf("resource group name is %s, expected %s", cg.Name, containerGroup)
}
}
func TestListContainerGroup(t *testing.T) {
list, err := client.ListContainerGroups(context.Background(), resourceGroup)
if err != nil {
t.Fatal(err)
}
for _, cg := range list.Value {
if cg.Name != containerGroup {
t.Fatalf("resource group name is %s, expected %s", cg.Name, containerGroup)
}
}
}
func TestCreateContainerGroupWithLivenessProbe(t *testing.T) {
uid := uuid.New()
containerGroupName := containerGroup + "-" + uid.String()[0:6]
cg, err := client.CreateContainerGroup(context.Background(), resourceGroup, containerGroupName, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
Limits: &ResourceLimits{
CPU: 1,
MemoryInGB: 1,
},
},
LivenessProbe: &ContainerProbe{
HTTPGet: &ContainerHTTPGetProbe{
Port: 80,
},
},
},
},
},
},
})
if err != nil {
t.Fatal(err)
}
if cg.Name != containerGroupName {
t.Fatalf("resource group name is %s, expected %s", cg.Name, containerGroupName)
}
}
func TestCreateContainerGroupFailsWithLivenessProbeMissingPort(t *testing.T) {
uid := uuid.New()
containerGroupName := containerGroup + "-" + uid.String()[0:6]
_, err := client.CreateContainerGroup(context.Background(), resourceGroup, containerGroupName, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
Limits: &ResourceLimits{
CPU: 1,
MemoryInGB: 1,
},
},
LivenessProbe: &ContainerProbe{
HTTPGet: &ContainerHTTPGetProbe{
Path: "/",
},
},
},
},
},
},
})
if err == nil {
t.Fatal("expected failure")
}
}
func TestCreateContainerGroupWithReadinessProbe(t *testing.T) {
uid := uuid.New()
containerGroupName := containerGroup + "-" + uid.String()[0:6]
cg, err := client.CreateContainerGroup(context.Background(), resourceGroup, containerGroupName, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
Limits: &ResourceLimits{
CPU: 1,
MemoryInGB: 1,
},
},
ReadinessProbe: &ContainerProbe{
HTTPGet: &ContainerHTTPGetProbe{
Port: 80,
Path: "/",
},
InitialDelaySeconds: 5,
SuccessThreshold: 3,
FailureThreshold: 5,
TimeoutSeconds: 120,
},
},
},
},
},
})
if err != nil {
t.Fatal(err)
}
if cg.Name != containerGroupName {
t.Fatalf("resource group name is %s, expected %s", cg.Name, containerGroupName)
}
}
func TestCreateContainerGroupWithLogAnalytics(t *testing.T) {
diagnostics, err := NewContainerGroupDiagnosticsFromFile("../../../../loganalytics.json")
if err != nil {
t.Fatal(err)
}
cgname := "cgla"
cg, err := client.CreateContainerGroup(context.Background(), resourceGroup, cgname, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
Limits: &ResourceLimits{
CPU: 1,
MemoryInGB: 1,
},
},
},
},
},
Diagnostics: diagnostics,
},
})
if err != nil {
t.Fatal(err)
}
if cg.Name != cgname {
t.Fatalf("resource group name is %s, expected %s", cg.Name, cgname)
}
if err := client.DeleteContainerGroup(context.Background(), resourceGroup, cgname); err != nil {
t.Fatalf("Delete Container Group failed: %s", err.Error())
}
}
func TestCreateContainerGroupWithInvalidLogAnalytics(t *testing.T) {
law := &LogAnalyticsWorkspace{}
_, err := client.CreateContainerGroup(context.Background(), resourceGroup, containerGroup, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
Limits: &ResourceLimits{
CPU: 1,
MemoryInGB: 1,
},
},
},
},
},
Diagnostics: &ContainerGroupDiagnostics{
LogAnalytics: law,
},
},
})
if err == nil {
t.Fatal("TestCreateContainerGroupWithInvalidLogAnalytics should fail but encountered no errors")
}
}
func TestCreateContainerGroupWithVNet(t *testing.T) {
uid := uuid.New()
containerGroupName := containerGroup + "-" + uid.String()[0:6]
fakeKubeConfig := base64.StdEncoding.EncodeToString([]byte(uid.String()))
networkProfileId := "/subscriptions/ae43b1e3-c35d-4c8c-bc0d-f148b4c52b78/resourceGroups/aci-connector/providers/Microsoft.Network/networkprofiles/aci-connector-network-profile-westus"
diagnostics, err := NewContainerGroupDiagnosticsFromFile("../../../../loganalytics.json")
if err != nil {
t.Fatal(err)
}
diagnostics.LogAnalytics.LogType = LogAnlyticsLogTypeContainerInsights
cg, err := client.CreateContainerGroup(context.Background(), resourceGroup, containerGroupName, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
Limits: &ResourceLimits{
CPU: 1,
MemoryInGB: 1,
},
},
},
},
},
NetworkProfile: &NetworkProfileDefinition{
ID: networkProfileId,
},
Extensions: []*Extension{
&Extension{
Name: "kube-proxy",
Properties: &ExtensionProperties{
Type: ExtensionTypeKubeProxy,
Version: ExtensionVersion1_0,
Settings: map[string]string{
KubeProxyExtensionSettingClusterCIDR: "10.240.0.0/16",
KubeProxyExtensionSettingKubeVersion: KubeProxyExtensionKubeVersion,
},
ProtectedSettings: map[string]string{
KubeProxyExtensionSettingKubeConfig: fakeKubeConfig,
},
},
},
},
DNSConfig: &DNSConfig{
NameServers: []string{"1.1.1.1"},
},
Diagnostics: diagnostics,
},
})
if err != nil {
t.Fatal(err)
}
if cg.Name != containerGroupName {
t.Fatalf("resource group name is %s, expected %s", cg.Name, containerGroupName)
}
if err := client.DeleteContainerGroup(context.Background(), resourceGroup, containerGroupName); err != nil {
t.Fatalf("Delete Container Group failed: %s", err.Error())
}
}
func TestDeleteContainerGroup(t *testing.T) {
err := client.DeleteContainerGroup(context.Background(), resourceGroup, containerGroup)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,103 +0,0 @@
package api
import (
"net/url"
"testing"
)
const (
baseURI = "https://management.azure.com"
)
type expandTest struct {
in string
expansions map[string]string
want string
}
var expandTests = []expandTest{
// no expansions
{
"",
map[string]string{},
"https://management.azure.com",
},
// multiple expansions, no escaping
{
"subscriptions/{{.subscriptionId}}/resourceGroups/{{.resourceGroup}}/providers/Microsoft.ContainerInstance/containerGroups/{{.containerGroupName}}",
map[string]string{
"subscriptionId": "foo",
"resourceGroup": "bar",
"containerGroupName": "baz",
},
"https://management.azure.com/subscriptions/foo/resourceGroups/bar/providers/Microsoft.ContainerInstance/containerGroups/baz",
},
// one expansion, with hex escapes
{
"subscriptions/{{.subscriptionId}}/resourceGroups/{{.resourceGroup}}/providers/Microsoft.ContainerInstance/containerGroups/{{.containerGroupName}}",
map[string]string{
"subscriptionId": "foo/bar",
"resourceGroup": "bar",
"containerGroupName": "baz",
},
"https://management.azure.com/subscriptions/foo%2Fbar/resourceGroups/bar/providers/Microsoft.ContainerInstance/containerGroups/baz",
},
// one expansion, with space
{
"subscriptions/{{.subscriptionId}}/resourceGroups/{{.resourceGroup}}/providers/Microsoft.ContainerInstance/containerGroups/{{.containerGroupName}}",
map[string]string{
"subscriptionId": "foo and bar",
"resourceGroup": "bar",
"containerGroupName": "baz",
},
"https://management.azure.com/subscriptions/foo%20and%20bar/resourceGroups/bar/providers/Microsoft.ContainerInstance/containerGroups/baz",
},
// expansion not found
{
"subscriptions/{{.subscriptionId}}/resourceGroups/{{.resourceGroup}}/providers/Microsoft.ContainerInstance/containerGroups/{{.containerGroupName}}",
map[string]string{
"subscriptionId": "foo",
"containerGroupName": "baz",
},
"https://management.azure.com/subscriptions/foo/resourceGroups/%3Cno%20value%3E/providers/Microsoft.ContainerInstance/containerGroups/baz",
},
// utf-8 characters
{
"{{.bucket}}/get",
map[string]string{
"bucket": "£100",
},
"https://management.azure.com/%C2%A3100/get",
},
// punctuations
{
"{{.bucket}}/get",
map[string]string{
"bucket": `/\@:,.`,
},
"https://management.azure.com/%2F%5C%40%3A%2C./get",
},
// mis-matched brackets
{
"/{{.bucket/get",
map[string]string{
"bucket": "red",
},
"https://management.azure.com/%7B%7B.bucket/get",
},
}
func TestExpandURL(t *testing.T) {
for i, test := range expandTests {
uri := ResolveRelative(baseURI, test.in)
u, err := url.Parse(uri)
if err != nil {
t.Fatalf("Parsing url %q failed: %v", test.in, err)
}
ExpandURL(u, test.expansions)
got := u.String()
if got != test.want {
t.Errorf("got %q expected %q in test %d", got, test.want, i+1)
}
}
}

View File

@@ -1,45 +0,0 @@
package network
import (
"context"
"sync"
"testing"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network"
"github.com/Azure/go-autorest/autorest/azure/auth"
)
var vnetAuthOnce sync.Once
var azAuth autorest.Authorizer
func ensureVnet(t *testing.T, name string) {
vnetAuthOnce.Do(func() {
var err error
azAuth, err = auth.NewClientCredentialsConfig(testAuth.ClientID, testAuth.ClientSecret, testAuth.TenantID).Authorizer()
if err != nil {
t.Fatalf("error setting up client auth for vnet create: %v", err)
}
})
client := network.NewVirtualNetworksClient(testAuth.SubscriptionID)
client.Authorizer = azAuth
prefixes := []string{"10.0.0.0/24"}
result, err := client.CreateOrUpdate(context.Background(), resourceGroup, name, network.VirtualNetwork{
Name: &name,
Location: &location,
VirtualNetworkPropertiesFormat: &network.VirtualNetworkPropertiesFormat{
AddressSpace: &network.AddressSpace{
AddressPrefixes: &prefixes,
},
},
})
if err != nil {
t.Fatal(err)
}
if err := result.WaitForCompletion(context.Background(), client.Client); err != nil {
t.Fatal(err)
}
}

View File

@@ -1,76 +0,0 @@
package network
import (
"fmt"
"os"
"sync"
"testing"
"github.com/google/uuid"
"github.com/pkg/errors"
azure "github.com/virtual-kubelet/virtual-kubelet/providers/azure/client"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/resourcegroups"
)
var (
location = "westus"
resourceGroup = "virtual-kubelet-tests"
testAuth *azure.Authentication
)
func TestMain(m *testing.M) {
uid := uuid.New()
resourceGroup += "-" + uid.String()[0:6]
if err := setupAuth(); err != nil {
fmt.Fprintln(os.Stderr, "Error setting up auth:", err)
os.Exit(1)
}
c, err := resourcegroups.NewClient(testAuth, "unit-test")
if err != nil {
os.Exit(1)
}
_, err = c.CreateResourceGroup(resourceGroup, resourcegroups.Group{
Name: resourceGroup,
Location: location,
})
if err != nil {
os.Exit(1)
}
code := m.Run()
if err := c.DeleteResourceGroup(resourceGroup); err != nil {
fmt.Fprintln(os.Stderr, "error removing resource group:", err)
}
os.Exit(code)
}
var authOnce sync.Once
func setupAuth() error {
var err error
authOnce.Do(func() {
testAuth, err = azure.NewAuthenticationFromFile(os.Getenv("AZURE_AUTH_LOCATION"))
if err != nil {
testAuth, err = azure.NewAuthenticationFromFile("../../../../credentials.json")
}
if err != nil {
err = errors.Wrap(err, "failed to load Azure authentication file")
}
})
return err
}
func newTestClient(t *testing.T) *Client {
if err := setupAuth(); err != nil {
t.Fatal(err)
}
c, err := NewClient(testAuth, "unit-test")
if err != nil {
t.Fatal(err)
}
return c
}

View File

@@ -1,81 +0,0 @@
package network
import (
"path"
"testing"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network"
)
func TestGetProfileNotFound(t *testing.T) {
c := newTestClient(t)
p, err := c.GetProfile(resourceGroup, "someprofile")
if err == nil {
t.Fatalf("expect error when getting the non-exist profile: %v", p)
}
if !IsNotFound(err) {
t.Fatal("expect NotFound error")
}
if p != nil {
t.Fatal("unexpected profile")
}
}
func TestCreateGetProfile(t *testing.T) {
c := newTestClient(t)
ensureVnet(t, t.Name())
subnet := NewSubnetWithContainerInstanceDelegation(t.Name(), "10.0.0.0/24")
subnet, err := c.CreateOrUpdateSubnet(resourceGroup, t.Name(), subnet)
if err != nil {
t.Fatal(err)
}
p := NewNetworkProfile(t.Name(), location, *subnet.ID)
p1, err := c.CreateOrUpdateProfile(resourceGroup, p)
if err != nil {
t.Fatal(err)
}
if p1 == nil {
t.Fatal("create profile should return profile")
}
if p1.ID == nil || *p1.ID == "" {
t.Fatal("create profile should return profile.ID")
}
var p2 *network.Profile
p2, err = c.GetProfile(resourceGroup, *p.Name)
if err != nil {
t.Fatal(err)
}
if len(*p2.ProfilePropertiesFormat.ContainerNetworkInterfaceConfigurations) != 1 {
t.Fatalf("got unexpected profile properties: %+v", *p2.ProfilePropertiesFormat)
}
containterNetworkInterfaceConfiguration := (*p2.ProfilePropertiesFormat.ContainerNetworkInterfaceConfigurations)[0]
if len(*containterNetworkInterfaceConfiguration.ContainerNetworkInterfaceConfigurationPropertiesFormat.IPConfigurations) != 1 {
t.Fatalf("got unexpected profile IP configuration: %+v", *containterNetworkInterfaceConfiguration.ContainerNetworkInterfaceConfigurationPropertiesFormat.IPConfigurations)
}
ipConfiguration := (*containterNetworkInterfaceConfiguration.ContainerNetworkInterfaceConfigurationPropertiesFormat.IPConfigurations)[0]
if *ipConfiguration.IPConfigurationProfilePropertiesFormat.Subnet.ID != *subnet.ID {
t.Fatal("got unexpected subnet")
}
subnet, err = c.GetSubnet(resourceGroup, t.Name(), t.Name())
if err != nil {
t.Fatal(err)
}
if len(*subnet.SubnetPropertiesFormat.IPConfigurationProfiles) != 1 {
t.Fatalf("got unexpected subnet IP configuration profiles: %+v", *subnet.SubnetPropertiesFormat.IPConfigurationProfiles)
}
expected := path.Join(*p2.ID, "containerNetworkInterfaceConfigurations/eth0/ipConfigurations/ipconfigprofile1")
if *(*subnet.SubnetPropertiesFormat.IPConfigurationProfiles)[0].ID != expected {
t.Fatalf("got unexpected profile, expected:\n\t%s, got:\n\t%s", expected, *(*subnet.SubnetPropertiesFormat.IPConfigurationProfiles)[0].ID)
}
}

View File

@@ -1,44 +0,0 @@
package network
import (
"testing"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network"
)
func TestCreateGetSubnet(t *testing.T) {
c := newTestClient(t)
subnet := NewSubnetWithContainerInstanceDelegation(t.Name(), "10.0.0.0/24")
ensureVnet(t, t.Name())
s1, err := c.CreateOrUpdateSubnet(resourceGroup, t.Name(), subnet)
if err != nil {
t.Fatal(err)
}
if s1 == nil {
t.Fatal("create subnet should return subnet")
}
if s1.ID == nil || *s1.ID == "" {
t.Fatal("create subnet should return subnet.ID")
}
var s2 *network.Subnet
s2, err = c.GetSubnet(resourceGroup, t.Name(), *subnet.Name)
if err != nil {
t.Fatal(err)
}
if *s2.Name != *subnet.Name {
t.Fatal("got unexpected subnet")
}
if *s2.SubnetPropertiesFormat.AddressPrefix != *subnet.SubnetPropertiesFormat.AddressPrefix {
t.Fatalf("got unexpected address prefix: %s", *s2.SubnetPropertiesFormat.AddressPrefix)
}
if len(*s2.SubnetPropertiesFormat.Delegations) != 1 {
t.Fatalf("got unexpected delgations: %v", *s2.SubnetPropertiesFormat.Delegations)
}
if *(*s2.SubnetPropertiesFormat.Delegations)[0].Name != *(*subnet.SubnetPropertiesFormat.Delegations)[0].Name {
t.Fatalf("got unexpected delegation: %v", (*s2.SubnetPropertiesFormat.Delegations)[0])
}
}

View File

@@ -1,45 +0,0 @@
package resourcegroups
import (
"fmt"
"net/http"
azure "github.com/virtual-kubelet/virtual-kubelet/providers/azure/client"
)
const (
// BaseURI is the default URI used for compute services.
BaseURI = "https://management.azure.com"
defaultUserAgent = "virtual-kubelet/azure-arm-resourcegroups/2017-12-01"
apiVersion = "2017-08-01"
resourceGroupURLPath = "subscriptions/{{.subscriptionId}}/resourcegroups/{{.resourceGroupName}}"
)
// Client is a client for interacting with Azure resource groups.
//
// Clients should be reused instead of created as needed.
// The methods of Client are safe for concurrent use by multiple goroutines.
type Client struct {
hc *http.Client
auth *azure.Authentication
}
// NewClient creates a new Azure resource groups client.
func NewClient(auth *azure.Authentication, extraUserAgent string) (*Client, error) {
if auth == nil {
return nil, fmt.Errorf("Authentication is not supplied for the Azure client")
}
userAgent := []string{defaultUserAgent}
if extraUserAgent != "" {
userAgent = append(userAgent, extraUserAgent)
}
client, err := azure.NewClient(auth, BaseURI, userAgent)
if err != nil {
return nil, fmt.Errorf("Creating Azure client failed: %v", err)
}
return &Client{hc: client.HTTPClient, auth: auth}, nil
}

View File

@@ -1,85 +0,0 @@
package resourcegroups
import (
"testing"
"github.com/google/uuid"
azure "github.com/virtual-kubelet/virtual-kubelet/providers/azure/client"
)
var (
client *Client
location = "eastus"
resourceGroup = "virtual-kubelet-tests"
)
func init() {
// Create a resource group name with uuid.
uid := uuid.New()
resourceGroup += "-" + uid.String()[0:6]
}
func TestNewClient(t *testing.T) {
auth, err := azure.NewAuthenticationFromFile("../../../../credentials.json")
if err != nil {
t.Fatalf("Failed to load Azure authentication file: %v", err)
}
c, err := NewClient(auth, "unit-test")
if err != nil {
t.Fatal(err)
}
client = c
}
func TestResourceGroupDoesNotExist(t *testing.T) {
exists, err := client.ResourceGroupExists(resourceGroup)
if err != nil {
t.Fatal(err)
}
if exists {
t.Fatal("resource group should not exist before it has been created")
}
}
func TestCreateResourceGroup(t *testing.T) {
g, err := client.CreateResourceGroup(resourceGroup, Group{
Location: location,
})
if err != nil {
t.Fatal(err)
}
// check the name is the same
if g.Name != resourceGroup {
t.Fatalf("resource group name is %s, expected virtual-kubelet-tests", g.Name)
}
}
func TestResourceGroupExists(t *testing.T) {
exists, err := client.ResourceGroupExists(resourceGroup)
if err != nil {
t.Fatal(err)
}
if !exists {
t.Fatal("resource group should exist after being created")
}
}
func TestGetResourceGroup(t *testing.T) {
g, err := client.GetResourceGroup(resourceGroup)
if err != nil {
t.Fatal(err)
}
// check the name is the same
if g.Name != resourceGroup {
t.Fatalf("resource group name is %s, expected %s", g.Name, resourceGroup)
}
}
func TestDeleteResourceGroup(t *testing.T) {
err := client.DeleteResourceGroup(resourceGroup)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,68 +0,0 @@
package resourcegroups
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
)
// CreateResourceGroup creates a new Azure resource group with the
// provided properties.
// From: https://docs.microsoft.com/en-us/rest/api/resources/resourcegroups/createorupdate
func (c *Client) CreateResourceGroup(resourceGroup string, properties Group) (*Group, error) {
urlParams := url.Values{
"api-version": []string{apiVersion},
}
// Create the url.
uri := api.ResolveRelative(BaseURI, resourceGroupURLPath)
uri += "?" + url.Values(urlParams).Encode()
// Create the body for the request.
b := new(bytes.Buffer)
if err := json.NewEncoder(b).Encode(properties); err != nil {
return nil, fmt.Errorf("Encoding create resource group body request failed: %v", err)
}
// Create the request.
req, err := http.NewRequest("PUT", uri, b)
if err != nil {
return nil, fmt.Errorf("Creating create/update resource group uri request failed: %v", err)
}
// Add the parameters to the url.
if err := api.ExpandURL(req.URL, map[string]string{
"subscriptionId": c.auth.SubscriptionID,
"resourceGroupName": resourceGroup,
}); err != nil {
return nil, fmt.Errorf("Expanding URL with parameters failed: %v", err)
}
// Send the request.
resp, err := c.hc.Do(req)
if err != nil {
return nil, fmt.Errorf("Sending create resource group request failed: %v", err)
}
defer resp.Body.Close()
// 200 (OK) and 201 (Created) are a successful responses.
if err := api.CheckResponse(resp); err != nil {
return nil, err
}
// Decode the body from the response.
if resp.Body == nil {
return nil, errors.New("Create resource group returned an empty body in the response")
}
var g Group
if err := json.NewDecoder(resp.Body).Decode(&g); err != nil {
return nil, fmt.Errorf("Decoding create resource group response body failed: %v", err)
}
return &g, nil
}

View File

@@ -1,54 +0,0 @@
package resourcegroups
import (
"fmt"
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
)
// DeleteResourceGroup deletes an Azure resource group.
// From: https://docs.microsoft.com/en-us/rest/api/resources/resourcegroups/delete
func (c *Client) DeleteResourceGroup(resourceGroup string) error {
urlParams := url.Values{
"api-version": []string{apiVersion},
}
// Create the url.
uri := api.ResolveRelative(BaseURI, resourceGroupURLPath)
uri += "?" + url.Values(urlParams).Encode()
// Create the request.
req, err := http.NewRequest("DELETE", uri, nil)
if err != nil {
return fmt.Errorf("Creating delete resource group uri request failed: %v", err)
}
// Add the parameters to the url.
if err := api.ExpandURL(req.URL, map[string]string{
"subscriptionId": c.auth.SubscriptionID,
"resourceGroupName": resourceGroup,
}); err != nil {
return fmt.Errorf("Expanding URL with parameters failed: %v", err)
}
// Send the request.
resp, err := c.hc.Do(req)
if err != nil {
return fmt.Errorf("Sending delete resource group request failed: %v", err)
}
defer resp.Body.Close()
// 200 (OK) and 202 (Accepted) are successful responses.
if err := api.CheckResponse(resp); err != nil {
return err
}
// 204 No Content means the specified resource group was not found.
if resp.StatusCode == http.StatusNoContent {
return fmt.Errorf("Resource group with name %q was not found", resourceGroup)
}
return nil
}

View File

@@ -1,3 +0,0 @@
// Package resourcegroups provides tools for interacting with the
// Azure Resource Manager resource groups API.
package resourcegroups

View File

@@ -1,60 +0,0 @@
package resourcegroups
import (
"fmt"
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
)
// ResourceGroupExists checks if an Azure resource group exists.
// From: https://docs.microsoft.com/en-us/rest/api/resources/resourcegroups/checkexistence
func (c *Client) ResourceGroupExists(resourceGroup string) (bool, error) {
urlParams := url.Values{
"api-version": []string{apiVersion},
}
// Create the url.
uri := api.ResolveRelative(BaseURI, resourceGroupURLPath)
uri += "?" + url.Values(urlParams).Encode()
// Create the request.
req, err := http.NewRequest("HEAD", uri, nil)
if err != nil {
return false, fmt.Errorf("Creating resource group exists uri request failed: %v", err)
}
// Add the parameters to the url.
if err := api.ExpandURL(req.URL, map[string]string{
"subscriptionId": c.auth.SubscriptionID,
"resourceGroupName": resourceGroup,
}); err != nil {
return false, fmt.Errorf("Expanding URL with parameters failed: %v", err)
}
// Send the request.
resp, err := c.hc.Do(req)
if err != nil {
return false, fmt.Errorf("Sending resource group exists request failed: %v", err)
}
defer resp.Body.Close()
// A 404 response means it does not exit.
if resp.StatusCode == http.StatusNotFound {
return false, nil
}
// 204 (NoContent) and 404 are successful responses.
if err := api.CheckResponse(resp); err != nil {
return false, err
}
// A 204 status means it exists.
if resp.StatusCode == http.StatusNoContent {
return true, nil
}
// A 404 status means it does not exist.
return false, nil
}

View File

@@ -1,60 +0,0 @@
package resourcegroups
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
)
// GetResourceGroup gets an Azure resource group.
// From: https://docs.microsoft.com/en-us/rest/api/resources/ResourceGroups/Get
func (c *Client) GetResourceGroup(resourceGroup string) (*Group, error) {
urlParams := url.Values{
"api-version": []string{apiVersion},
}
// Create the url.
uri := api.ResolveRelative(BaseURI, resourceGroupURLPath)
uri += "?" + url.Values(urlParams).Encode()
// Create the request.
req, err := http.NewRequest("GET", uri, nil)
if err != nil {
return nil, fmt.Errorf("Creating get resource group uri request failed: %v", err)
}
// Add the parameters to the url.
if err := api.ExpandURL(req.URL, map[string]string{
"subscriptionId": c.auth.SubscriptionID,
"resourceGroupName": resourceGroup,
}); err != nil {
return nil, fmt.Errorf("Expanding URL with parameters failed: %v", err)
}
// Send the request.
resp, err := c.hc.Do(req)
if err != nil {
return nil, fmt.Errorf("Sending get resource group request failed: %v", err)
}
defer resp.Body.Close()
// 200 (OK) is a success response.
if err := api.CheckResponse(resp); err != nil {
return nil, err
}
// Decode the body from the response.
if resp.Body == nil {
return nil, errors.New("Create resource group returned an empty body in the response")
}
var g Group
if err := json.NewDecoder(resp.Body).Decode(&g); err != nil {
return nil, fmt.Errorf("Decoding get resource group response body failed: %v", err)
}
return &g, nil
}

View File

@@ -1,19 +0,0 @@
package resourcegroups
import "github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
// Group holds resource group information.
type Group struct {
api.ResponseMetadata `json:"-"`
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Properties *GroupProperties `json:"properties,omitempty"`
Location string `json:"location,omitempty"`
ManagedBy string `json:"managedBy,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
}
// GroupProperties deines the properties for an Azure resource group.
type GroupProperties struct {
ProvisioningState string `json:"provisioningState,omitempty"`
}

View File

@@ -1,8 +0,0 @@
package resourcegroups
// UpdateResourceGroup updates an Azure resource group with the
// provided properties.
// From: https://docs.microsoft.com/en-us/rest/api/resources/resourcegroups/createorupdate
func (c *Client) UpdateResourceGroup(resourceGroup string, properties Group) (*Group, error) {
return c.CreateResourceGroup(resourceGroup, properties)
}

View File

@@ -4,7 +4,7 @@ import (
"net/http"
"github.com/cpuguy83/strongerrors"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
func wrapError(err error) error {

View File

@@ -7,8 +7,8 @@ import (
"github.com/cpuguy83/strongerrors/status/ocstatus"
"github.com/pkg/errors"
"github.com/virtual-kubelet/azure-aci/client/aci"
"github.com/virtual-kubelet/virtual-kubelet/log"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/aci"
"github.com/virtual-kubelet/virtual-kubelet/trace"
"golang.org/x/sync/errgroup"
v1 "k8s.io/api/core/v1"

View File

@@ -7,8 +7,8 @@ import (
"testing"
"time"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/aci"
"k8s.io/api/core/v1"
"github.com/virtual-kubelet/azure-aci/client/aci"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
@@ -42,7 +42,7 @@ func TestCollectMetrics(t *testing.T) {
t.Fatalf("got unexpected container\nexpected:\n%+v\nactual:\n%+v", expectedContainer, actualContainer)
}
found = true
break;
break
}
}

201
vendor/github.com/virtual-kubelet/azure-aci/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,201 @@
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.

View File

@@ -8,7 +8,7 @@ import (
"go.opencensus.io/plugin/ochttp"
azure "github.com/virtual-kubelet/virtual-kubelet/providers/azure/client"
azure "github.com/virtual-kubelet/azure-aci/client"
)
const (

View File

@@ -9,7 +9,7 @@ import (
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
// CreateContainerGroup creates a new Azure Container Instance with the

View File

@@ -6,7 +6,7 @@ import (
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
// DeleteContainerGroup deletes an Azure Container Instance in the provided

View File

@@ -8,8 +8,7 @@ import (
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"k8s.io/client-go/tools/remotecommand"
"github.com/virtual-kubelet/azure-aci/client/api"
)
type TerminalSizeRequest struct {
@@ -19,7 +18,7 @@ type TerminalSizeRequest struct {
// Starts the exec command for a specified container instance in a specified resource group and container group.
// From: https://docs.microsoft.com/en-us/rest/api/container-instances/startcontainer/launchexec
func (c *Client) LaunchExec(resourceGroup, containerGroupName, containerName, command string, terminalSize remotecommand.TerminalSize) (ExecResponse, error) {
func (c *Client) LaunchExec(resourceGroup, containerGroupName, containerName, command string, terminalSize TerminalSizeRequest) (ExecResponse, error) {
urlParams := url.Values{
"api-version": []string{apiVersion},
}
@@ -31,8 +30,8 @@ func (c *Client) LaunchExec(resourceGroup, containerGroupName, containerName, co
var xc ExecRequest
xc.Command = command
xc.TerminalSize.Rows = int(terminalSize.Height)
xc.TerminalSize.Cols = int(terminalSize.Width)
xc.TerminalSize.Rows = terminalSize.Height
xc.TerminalSize.Cols = terminalSize.Width
var xcrsp ExecResponse
xcrsp.Password = ""

View File

@@ -8,7 +8,7 @@ import (
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
// GetContainerGroup gets an Azure Container Instance in the provided

View File

@@ -8,7 +8,7 @@ import (
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
// ListContainerGroups lists an Azure Container Instance Groups, if a resource

View File

@@ -8,7 +8,7 @@ import (
"net/http"
"net/url"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
// GetContainerLogs returns the logs from an Azure Container Instance

View File

@@ -9,7 +9,7 @@ import (
"time"
"github.com/pkg/errors"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
// GetContainerGroupMetrics gets metrics for the provided container group

View File

@@ -3,7 +3,7 @@ package aci
import (
"time"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
// ContainerGroupNetworkProtocol enumerates the values for container group network protocol.

View File

@@ -6,8 +6,8 @@ import (
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network"
"github.com/Azure/go-autorest/autorest/azure/auth"
azure "github.com/virtual-kubelet/virtual-kubelet/providers/azure/client"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
azure "github.com/virtual-kubelet/azure-aci/client"
"github.com/virtual-kubelet/azure-aci/client/api"
)
const (

View File

@@ -8,7 +8,7 @@ import (
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network"
"github.com/pkg/errors"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
const (
@@ -21,7 +21,7 @@ var (
)
// NewNetworkProfile creates a new instance of network profile
func NewNetworkProfile(name, location, subnetID string ) *network.Profile {
func NewNetworkProfile(name, location, subnetID string) *network.Profile {
p := network.Profile{
Name: &name,
Location: &location,
@@ -132,20 +132,20 @@ func (c *Client) CreateOrUpdateProfile(resourceGroup string, p *network.Profile)
}
defer resp.Body.Close()
// 200 (OK) is a success response.
if err := api.CheckResponse(resp); err != nil {
return nil, err
}
// 200 (OK) is a success response.
if err := api.CheckResponse(resp); err != nil {
return nil, err
}
// Decode the body from the response.
if resp.Body == nil {
return nil, errors.New("create network profile returned an empty body in the response")
}
// Decode the body from the response.
if resp.Body == nil {
return nil, errors.New("create network profile returned an empty body in the response")
}
var profile network.Profile
if err := json.NewDecoder(resp.Body).Decode(&profile); err != nil {
return nil, errors.Wrap(err, "decoding create network profile response body failed")
}
var profile network.Profile
if err := json.NewDecoder(resp.Body).Decode(&profile); err != nil {
return nil, errors.Wrap(err, "decoding create network profile response body failed")
}
return &profile, nil
}

View File

@@ -8,12 +8,12 @@ import (
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network"
"github.com/pkg/errors"
"github.com/virtual-kubelet/virtual-kubelet/providers/azure/client/api"
"github.com/virtual-kubelet/azure-aci/client/api"
)
const (
subnetPath = "subscriptions/{{.subscriptionId}}/resourcegroups/{{.resourceGroupName}}/providers/Microsoft.Network/virtualNetworks/{{.vnetName}}/subnets/{{.subnetName}}"
subnetAction = "Microsoft.Network/virtualNetworks/subnets/action"
subnetPath = "subscriptions/{{.subscriptionId}}/resourcegroups/{{.resourceGroupName}}/providers/Microsoft.Network/virtualNetworks/{{.vnetName}}/subnets/{{.subnetName}}"
subnetAction = "Microsoft.Network/virtualNetworks/subnets/action"
)
var (