forked from open-telemetry/opentelemetry-collector-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add resourcedetection for cycle.io platform
- Loading branch information
1 parent
0207370
commit cd60f76
Showing
6 changed files
with
344 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
processor/resourcedetectionprocessor/internal/cycleio/config.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package cycleio | ||
|
||
type Config struct { | ||
} | ||
|
||
func CreateDefaultConfig() Config { | ||
return Config{} | ||
} |
184 changes: 184 additions & 0 deletions
184
processor/resourcedetectionprocessor/internal/cycleio/cycleio.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// Package env provides a detector that loads resource information from | ||
// the OTEL_RESOURCE environment variable. A list of labels of the form | ||
// `<key1>=<value1>,<key2>=<value2>,...` is accepted. Domain names and | ||
// paths are accepted as label keys. | ||
package cycleio // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/cycleio" | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net" | ||
"net/http" | ||
"net/url" | ||
"os" | ||
|
||
"go.opentelemetry.io/collector/pdata/pcommon" | ||
"go.opentelemetry.io/collector/processor" | ||
semconv "go.opentelemetry.io/collector/semconv/v1.5.0" | ||
|
||
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" | ||
) | ||
|
||
// TypeStr is type of detector. | ||
const ( | ||
TypeStr = "cycleio" | ||
providerVendorEnvVar = "CYCLE_PROVIDER_VENDOR" | ||
providerLocation = "CYCLE_PROVIDER_LOCATION" | ||
hostnameEnvVar = "CYCLE_SERVER_ID" | ||
clusterEnvVar = "CYCLE_CLUSTER" | ||
|
||
cycleAPITokenEnvVar = "CYCLE_API_TOKEN" | ||
cycleAPIUnixSocket = "/var/run/cycle/api/api.sock" | ||
cycleAPIHost = "localhost" | ||
cycleAPIServerEndpoint = "/v1/server" | ||
|
||
cycleTokenHeader = "X-CYCLE-TOKEN" | ||
) | ||
|
||
var _ internal.Detector = (*Detector)(nil) | ||
|
||
type cycleProvider struct { | ||
Vendor string `json:"vendor"` | ||
Model string `json:"model"` | ||
Location string `json:"location"` | ||
Zone string `json:"zone"` | ||
Server string `json:"server"` | ||
InitIPs []any `json:"init_ips"` | ||
} | ||
|
||
type cycleServerData struct { | ||
ID string `json:"id"` | ||
Hostname string `json:"hostname"` | ||
Provider cycleProvider `json:"provider"` | ||
Cluster string `json:"cluster"` | ||
} | ||
|
||
type cycleServerInfo struct { | ||
Data cycleServerData `json:"data"` | ||
} | ||
|
||
type Detector struct{} | ||
|
||
func NewDetector(processor.Settings, internal.DetectorConfig) (internal.Detector, error) { | ||
return &Detector{}, nil | ||
} | ||
|
||
func (d *Detector) Detect(context.Context) (resource pcommon.Resource, schemaURL string, err error) { | ||
res := pcommon.NewResource() | ||
|
||
res.Attributes().PutStr(semconv.AttributeOSType, semconv.AttributeOSTypeLinux) | ||
cycleAPIToken := os.Getenv(cycleAPITokenEnvVar) | ||
if cycleAPIToken != "" { | ||
serverInfo, err := getServerInfo(cycleAPIToken) | ||
if err != nil { | ||
return res, "", err | ||
} | ||
data := serverInfo.Data | ||
|
||
res.Attributes().PutStr(semconv.AttributeCloudProvider, getCloudProvider(data.Provider.Vendor)) | ||
res.Attributes().PutStr(semconv.AttributeCloudRegion, data.Provider.Location) | ||
res.Attributes().PutStr(semconv.AttributeCloudAvailabilityZone, data.Provider.Zone) | ||
res.Attributes().PutStr(semconv.AttributeHostID, data.ID) | ||
res.Attributes().PutStr(semconv.AttributeHostName, data.Hostname) | ||
res.Attributes().PutStr(semconv.AttributeHostType, data.Provider.Model) | ||
res.Attributes().PutEmptySlice("host.ip").FromRaw(data.Provider.InitIPs) | ||
|
||
res.Attributes().PutStr("cycle.cluster.id", data.Cluster) | ||
} else { | ||
|
||
vendor := os.Getenv(providerVendorEnvVar) | ||
if vendor == "" { | ||
vendor = "unknown" | ||
} | ||
res.Attributes().PutStr(semconv.AttributeCloudProvider, getCloudProvider(vendor)) | ||
|
||
region := os.Getenv(providerLocation) | ||
if region == "" { | ||
region = "unknown" | ||
} | ||
res.Attributes().PutStr(semconv.AttributeCloudRegion, region) | ||
|
||
hostID := os.Getenv(hostnameEnvVar) | ||
if hostID == "" { | ||
hostID = "cycleio-server" | ||
} | ||
res.Attributes().PutStr(semconv.AttributeHostID, hostID) | ||
res.Attributes().PutStr(semconv.AttributeHostName, hostID) | ||
|
||
cluster := os.Getenv(clusterEnvVar) | ||
if cluster == "" { | ||
cluster = "unknown" | ||
} | ||
res.Attributes().PutStr("cycle.cluster.id", cluster) | ||
} | ||
|
||
return res, "", nil | ||
} | ||
|
||
func getCloudProvider(provider string) string { | ||
switch provider { | ||
case "aws": | ||
return semconv.AttributeCloudProviderAWS | ||
case "gcp": | ||
return semconv.AttributeCloudProviderGCP | ||
case "azure": | ||
return semconv.AttributeCloudProviderAzure | ||
default: | ||
return provider | ||
} | ||
} | ||
|
||
func getServerInfo(token string) (*cycleServerInfo, error) { | ||
var serverInfo cycleServerInfo | ||
|
||
// Create a custom HTTP transport that uses the Unix socket | ||
transport := &http.Transport{ | ||
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { | ||
return net.Dial("unix", cycleAPIUnixSocket) | ||
}, | ||
} | ||
|
||
// Create an HTTP client with the custom transport | ||
client := &http.Client{ | ||
Transport: transport, | ||
} | ||
|
||
// Construct the request URL | ||
u := &url.URL{ | ||
Scheme: "http", | ||
Host: cycleAPIHost, // This is ignored but required for forming a valid URL | ||
Path: cycleAPIServerEndpoint, | ||
} | ||
|
||
req, err := http.NewRequest("GET", u.String(), nil) | ||
if err != nil { | ||
return &serverInfo, err | ||
} | ||
req.Header.Add(cycleTokenHeader, token) | ||
resp, err := client.Do(req) | ||
if err != nil { | ||
return &serverInfo, err | ||
} | ||
|
||
defer resp.Body.Close() | ||
|
||
// Read and print the response | ||
body, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
return &serverInfo, err | ||
} | ||
|
||
fmt.Println("###", string(body)) | ||
err = json.Unmarshal(body, &serverInfo) | ||
if err != nil { | ||
return &serverInfo, err | ||
} | ||
|
||
fmt.Println("###", serverInfo) | ||
return &serverInfo, nil | ||
} |
130 changes: 130 additions & 0 deletions
130
processor/resourcedetectionprocessor/internal/cycleio/cycleio_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package cycleio | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
"go.opentelemetry.io/collector/processor" | ||
semconv "go.opentelemetry.io/collector/semconv/v1.5.0" | ||
) | ||
|
||
// TODO | ||
func TestDetect(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
env map[string]string | ||
want map[string]interface{} | ||
}{ | ||
{ | ||
name: "empty env", | ||
env: map[string]string{}, | ||
want: map[string]interface{}{ | ||
semconv.AttributeCloudProvider: "unknown", | ||
semconv.AttributeCloudRegion: "unknown", | ||
semconv.AttributeHostID: "cycleio-server", | ||
semconv.AttributeHostName: "cycleio-server", | ||
semconv.AttributeOSType: semconv.AttributeOSTypeLinux, | ||
"cycle.cluster.id": "unknown", | ||
}, | ||
}, | ||
{ | ||
name: "only provider vendor", | ||
env: map[string]string{ | ||
providerVendorEnvVar: "aws", | ||
}, | ||
want: map[string]interface{}{ | ||
semconv.AttributeCloudProvider: "aws", | ||
semconv.AttributeCloudRegion: "unknown", | ||
semconv.AttributeHostID: "cycleio-server", | ||
semconv.AttributeHostName: "cycleio-server", | ||
semconv.AttributeOSType: semconv.AttributeOSTypeLinux, | ||
"cycle.cluster.id": "unknown", | ||
}, | ||
}, | ||
{ | ||
name: "only provider location", | ||
env: map[string]string{ | ||
providerVendorEnvVar: "aws", | ||
providerLocation: "us-east-1", | ||
}, | ||
want: map[string]interface{}{ | ||
semconv.AttributeCloudProvider: "aws", | ||
semconv.AttributeCloudRegion: "us-east-1", | ||
semconv.AttributeHostID: "cycleio-server", | ||
semconv.AttributeHostName: "cycleio-server", | ||
semconv.AttributeOSType: semconv.AttributeOSTypeLinux, | ||
"cycle.cluster.id": "unknown", | ||
}, | ||
}, | ||
{ | ||
name: "only hostname", | ||
env: map[string]string{ | ||
hostnameEnvVar: "acme-host", | ||
}, | ||
want: map[string]interface{}{ | ||
semconv.AttributeCloudProvider: "unknown", | ||
semconv.AttributeCloudRegion: "unknown", | ||
semconv.AttributeHostID: "acme-host", | ||
semconv.AttributeHostName: "acme-host", | ||
semconv.AttributeOSType: semconv.AttributeOSTypeLinux, | ||
"cycle.cluster.id": "unknown", | ||
}, | ||
}, | ||
{ | ||
name: "only cluster", | ||
env: map[string]string{ | ||
clusterEnvVar: "acme-cluster", | ||
}, | ||
want: map[string]interface{}{ | ||
semconv.AttributeCloudProvider: "unknown", | ||
semconv.AttributeCloudRegion: "unknown", | ||
semconv.AttributeHostID: "cycleio-server", | ||
semconv.AttributeHostName: "cycleio-server", | ||
semconv.AttributeOSType: semconv.AttributeOSTypeLinux, | ||
"cycle.cluster.id": "acme-cluster", | ||
}, | ||
}, | ||
{ | ||
name: "all env vars", | ||
env: map[string]string{ | ||
providerVendorEnvVar: "aws", | ||
providerLocation: "us-east-1", | ||
hostnameEnvVar: "acme-host", | ||
clusterEnvVar: "acme-cluster", | ||
}, | ||
want: map[string]interface{}{ | ||
semconv.AttributeCloudProvider: "aws", | ||
semconv.AttributeCloudRegion: "us-east-1", | ||
semconv.AttributeHostID: "acme-host", | ||
semconv.AttributeHostName: "acme-host", | ||
semconv.AttributeOSType: semconv.AttributeOSTypeLinux, | ||
"cycle.cluster.id": "acme-cluster", | ||
}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
for key, value := range tt.env { | ||
os.Setenv(key, value) | ||
} | ||
defer func() { | ||
for key := range tt.env { | ||
os.Unsetenv(key) | ||
} | ||
}() | ||
|
||
d, err := NewDetector(processor.Settings{}, CreateDefaultConfig()) | ||
require.NoError(t, err) | ||
got, _, err := d.Detect(context.Background()) | ||
require.NoError(t, err) | ||
|
||
require.Equal(t, tt.want, got.Attributes().AsRaw()) | ||
}) | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
processor/resourcedetectionprocessor/internal/cycleio/package_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package cycleio | ||
|
||
import ( | ||
"testing" | ||
|
||
"go.uber.org/goleak" | ||
) | ||
|
||
func TestMain(m *testing.M) { | ||
goleak.VerifyTestMain(m) | ||
} |