Skip to content

Commit

Permalink
Plumb through log analytics values (#274)
Browse files Browse the repository at this point in the history
* plumb through log analytics values

* add option to specify a log analytics file as well

* use secret for log analytics
  • Loading branch information
rohancme authored and robbiezhang committed Jul 25, 2018
1 parent 28daffa commit ef6ae9e
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 21 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -26,6 +26,9 @@ bin/
# Test credentials file
credentials.json

# Test loganalytics file
loganalytics.json

# VS Code files
.vscode/

Expand Down
4 changes: 4 additions & 0 deletions charts/virtual-kubelet/templates/deployment.yaml
Expand Up @@ -26,6 +26,10 @@ spec:
value: /etc/virtual-kubelet/cert.pem
- name: APISERVER_KEY_LOCATION
value: /etc/virtual-kubelet/key.pem
{{ if .Values.loganalytics.enabled }}
- name: LOG_ANALYTICS_AUTH_LOCATION
value: /etc/virtual-kubelet/loganalytics.json
{{ end }}
- name: VKUBELET_POD_IP
valueFrom:
fieldRef:
Expand Down
3 changes: 3 additions & 0 deletions charts/virtual-kubelet/templates/secrets.yaml
Expand Up @@ -7,3 +7,6 @@ data:
credentials.json: {{ printf "{ \"clientId\": \"%s\", \"clientSecret\": \"%s\", \"subscriptionId\": \"%s\", \"tenantId\": \"%s\", \"activeDirectoryEndpointUrl\": \"https://login.microsoftonline.com/\", \"resourceManagerEndpointUrl\": \"https://management.azure.com/\", \"activeDirectoryGraphResourceId\": \"https://graph.windows.net/\", \"sqlManagementEndpointUrl\": \"database.windows.net\", \"galleryEndpointUrl\": \"https://gallery.azure.com/\", \"managementEndpointUrl\": \"https://management.core.windows.net/\" }" (default "MISSING" .Values.env.azureClientId) (default "MISSING" .Values.env.azureClientKey) (default "MISSING" .Values.env.azureSubscriptionId) (default "MISSING" .Values.env.azureTenantId) | b64enc | quote }}
cert.pem: {{ (default "TUlTU0lORw==" .Values.env.apiserverCert) | quote }}
key.pem: {{ (default "TUlTU0lORw==" .Values.env.apiserverKey) | quote }}
{{ if .Values.loganalytics.enabled }}
loganalytics.json: {{ printf "{\"workspaceID\": \"%s\",\"workspaceKey\": \"%s\"}" (required "workspaceID is required for loganalytics" .Values.loganalytics.workspaceID ) (required "workspaceKey is required for loganalytics" .Values.loganalytics.workspaceKey ) }}
{{ end }}
6 changes: 5 additions & 1 deletion charts/virtual-kubelet/values.yaml
Expand Up @@ -14,7 +14,11 @@ env:
nodeOsType:
apiserverCert:
apiserverKey:
monitoredNamespace:
monitoredNamespace:
loganalytics:
enabled: false
workspaceID:
workspaceKey:

# Install Default RBAC roles and bindings
rbac:
Expand Down
21 changes: 21 additions & 0 deletions providers/azure/aci.go
Expand Up @@ -44,6 +44,7 @@ type ACIProvider struct {
pods string
internalIP string
daemonEndpointPort int32
diagnostics *aci.ContainerGroupDiagnostics
}

// AuthConfig is the secret returned from an ImageRegistryCredential
Expand Down Expand Up @@ -155,6 +156,25 @@ func NewACIProvider(config string, rm *manager.ResourceManager, nodeName, operat
return nil, err
}

// If the log analytics file has been specified, load workspace credentials from the file
if logAnalyticsAuthFile := os.Getenv("LOG_ANALYTICS_AUTH_LOCATION"); logAnalyticsAuthFile != "" {
p.diagnostics, err = aci.NewContainerGroupDiagnosticsFromFile(logAnalyticsAuthFile)
if err != nil {
return nil, err
}
}

// If we have both the log analytics workspace id and key, add them to the provider
// Environment variables overwrite the values provided in the file
if logAnalyticsID := os.Getenv("LOG_ANALYTICS_ID"); logAnalyticsID != "" {
if logAnalyticsKey := os.Getenv("LOG_ANALYTICS_KEY"); logAnalyticsKey != "" {
p.diagnostics, err = aci.NewContainerGroupDiagnostics(logAnalyticsID, logAnalyticsKey)
if err != nil {
return nil, err
}
}
}

if rg := os.Getenv("ACI_RESOURCE_GROUP"); rg != "" {
p.resourceGroup = rg
}
Expand Down Expand Up @@ -227,6 +247,7 @@ func (p *ACIProvider) CreatePod(pod *v1.Pod) error {
containerGroup.ContainerGroupProperties.Containers = containers
containerGroup.ContainerGroupProperties.Volumes = volumes
containerGroup.ContainerGroupProperties.ImageRegistryCredentials = creds
containerGroup.ContainerGroupProperties.Diagnostics = p.diagnostics

filterServiceAccountSecretVolume(p.operatingSystem, &containerGroup)

Expand Down
26 changes: 26 additions & 0 deletions providers/azure/client/README.md
Expand Up @@ -38,3 +38,29 @@ The file looks like this, in case you want to create it yourself:
"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>"
}
```
39 changes: 39 additions & 0 deletions providers/azure/client/aci/analytics.go
@@ -0,0 +1,39 @@
package aci

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
)

func NewContainerGroupDiagnostics(logAnalyticsID, logAnalyticsKey string) (*ContainerGroupDiagnostics, error) {

if logAnalyticsID == "" || logAnalyticsKey == "" {
return nil, errors.New("Log Analytics configuration requires both the workspace ID and Key")
}

return &ContainerGroupDiagnostics{
LogAnalytics: &LogAnalyticsWorkspace{
WorkspaceID: logAnalyticsID,
WorkspaceKey: logAnalyticsKey,
},
}, nil
}

func NewContainerGroupDiagnosticsFromFile(filepath string) (*ContainerGroupDiagnostics, error) {

analyticsdata, err := ioutil.ReadFile(filepath)
if err != nil {
return nil, fmt.Errorf("Reading Log Analytics Auth file %q failed: %v", filepath, err)
}
// Unmarshal the log analytics file.
var law LogAnalyticsWorkspace
if err := json.Unmarshal(analyticsdata, &law); err != nil {
return nil, err
}

return &ContainerGroupDiagnostics{
LogAnalytics: &law,
}, nil
}
38 changes: 38 additions & 0 deletions providers/azure/client/aci/analytics_test.go
@@ -0,0 +1,38 @@
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")
}
}
22 changes: 2 additions & 20 deletions providers/azure/client/aci/client_test.go
@@ -1,9 +1,6 @@
package aci

import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
Expand Down Expand Up @@ -363,21 +360,8 @@ func TestCreateContainerGroupWithReadinessProbe(t *testing.T) {
}
}

func logAnalyticsWorkspaceFromFile(filepath string) (*LogAnalyticsWorkspace, error) {
analyticsdata, err := ioutil.ReadFile(filepath)
if err != nil {
return nil, fmt.Errorf("Reading LogAnalyticsWorkspace file %q failed: %v", filepath, err)
}
// Unmarshal the log analytics file.
var law LogAnalyticsWorkspace
if err := json.Unmarshal(analyticsdata, &law); err != nil {
return nil, err
}
return &law, nil
}

func TestCreateContainerGroupWithLogAnalytics(t *testing.T) {
law, err := logAnalyticsWorkspaceFromFile("../../../../loganalytics.json")
diagnostics, err := NewContainerGroupDiagnosticsFromFile("../../../../loganalytics.json")
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -411,9 +395,7 @@ func TestCreateContainerGroupWithLogAnalytics(t *testing.T) {
},
},
},
Diagnostics: &ContainerGroupDiagnostics{
LogAnalytics: law,
},
Diagnostics: diagnostics,
},
})
if err != nil {
Expand Down

0 comments on commit ef6ae9e

Please sign in to comment.