Skip to content

Commit fe474e3

Browse files
tomasmotam1rpjriguera
authored
[extensions/observer/cfgardenobserver] Implement cfgardenobserver (#34513)
**Description:** First Component PR: #33727 This is the second PR for adding the cfgardenobserver, with the first suggested implementation. There are definitely some decisions made that require feedback, such as adding the CloudFoundry application labels to the Endpoint labels, and the decision to use the `Container` EndpointType at all. **Link to tracking Issue:** #33618 **Testing:** Unit testing of config and extension **Documentation:** Updated readme with new configuration and endpoints --------- Co-authored-by: sam clulow <[email protected]> Co-authored-by: sam clulow <[email protected]> Co-authored-by: José Riguera Lopez <[email protected]>
1 parent 219011b commit fe474e3

File tree

13 files changed

+1004
-100
lines changed

13 files changed

+1004
-100
lines changed
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: new_component
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: extensions/observer/cfgardenobserver
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Implemented the observer, the second PR in the 3 PR process for new components
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [33618]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

extension/observer/cfgardenobserver/README.md

+36-13
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
| Stability | [development] |
77
| Distributions | [] |
88
| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aextension%2Fcfgardenobserver%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aextension%2Fcfgardenobserver) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aextension%2Fcfgardenobserver%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aextension%2Fcfgardenobserver) |
9-
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@crobert-1](https://www.github.com/crobert-1), [@cemdk](https://www.github.com/cemdk), [@tomasmota](https://www.github.com/tomasmota), [@m1rp](https://www.github.com/m1rp), [@jriguera](https://www.github.com/jriguera) |
9+
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@crobert-1](https://www.github.com/crobert-1), [@cemdk](https://www.github.com/cemdk), [@m1rp](https://www.github.com/m1rp), [@jriguera](https://www.github.com/jriguera) |
1010

1111
[development]: https://github.com/open-telemetry/opentelemetry-collector#development
1212
<!-- end autogenerated section -->
@@ -20,34 +20,57 @@ The `cfgarden_observer` looks at the current host to discover Garden containers.
2020
```yaml
2121
extensions:
2222
cfgarden_observer:
23-
# url of the Garden socket, defaults to unix:///var/vcap/data/garden/garden.sock
24-
endpoint: my/path/to/garden.sock
25-
# determines how often to look for changes in endpoints.
2623
refresh_interval: 30s
24+
cache_sync_interval: 10m
25+
include_app_labels: true
26+
garden:
27+
endpoint: my/path/to/garden.sock
28+
cloud_foundry:
29+
endpoint: https://api.cf.mydomain.com
30+
auth:
31+
type: client_credentials
32+
client_id: myclientid
33+
client_secret: myclientsecret
2734

2835
receivers:
2936
receiver_creator:
3037
watch_observers: [cfgarden_observer]
3138
receivers:
3239
prometheus_simple:
33-
rule: type == "container" && name == "myapp"
40+
rule: type == "container" && labels["prometheus.io/scrape"] == "true"
3441
config:
3542
metrics_path: /metrics
3643
endpoint: '`endpoint`'
3744
```
3845
3946
### Configuration
4047
41-
| Name | Type | Default | Docs |
42-
|------------------|--------|------------------------------------------|--------------------------------------------------------|
43-
| refresh_interval | string | 60s | Determines how often to look for changes in endpoints. |
44-
| endpoint | string | unix:///var/vcap/data/garden/garden.sock | The endpoint to connect to the Garden API. |
48+
| Name | Type | Default | Description |
49+
| -------------------------------- | ------ | --------------------------------------------------------- | ------------------------------------------------------------------ |
50+
| refresh_interval | string | 1m | Determines how often to look for changes in endpoints. |
51+
| cache_sync_interval | string | 5m | Determines how often app metadata cache is refreshed |
52+
| include_app_labels | bool | false | Determines whether or not app labels get added to container labels |
53+
| garden.endpoint | string | /var/vcap/data/garden/garden.sock | Path to garden socket. |
54+
| cloud_foundry.endpoint | string | none. required when `include_app_labels` is set to `true` | CloudFoundry API endpoint |
55+
| cloud_foundry.auth.type | string | none. required when `include_app_labels` is set to `true` | Authentication type, one of: user_pass, client_credentials, token |
56+
| cloud_foundry.auth.username | string | none | Username (auth.type: user_pass) |
57+
| cloud_foundry.auth.password | string | none | Password (auth.type: user_pass) |
58+
| cloud_foundry.auth.client_id | string | none | Client ID (auth.type: client_credentials) |
59+
| cloud_foundry.auth.client_secret | string | none | Client Secret (auth.type: client_credentials) |
60+
| cloud_foundry.auth.access_token | string | none | Access Token (auth.type: token) |
61+
| cloud_foundry.auth.refresh_token | string | none | Refresh Token (auth.type: token) |
62+
4563

4664
### Endpoint Variables
4765

4866
Endpoint variables exposed by this observer are as follows.
4967

50-
| Variable | Description |
51-
|-----------|--------------------------------------------------------------------------------------------|
52-
| type | this value is always `container` |
53-
| name | name of the Garden container associated to the port |
68+
| Variable | Description |
69+
| ------------ | --------------------------------------------------------------------------------- |
70+
| type | This value is always `container` |
71+
| name | Name of the Garden container associated to the port |
72+
| labels | map[string]string with labels set on the log_config tags and application resource |
73+
| port | Exposed port of the container |
74+
| container_id | ID of the container |
75+
| host | Hostname or IP of the underlying host the container is running on |
76+
| transport | Transport protocol used by the endpoint (TCP or UDP) |

extension/observer/cfgardenobserver/config.go

+108-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,121 @@
44
package cfgardenobserver // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer/cfgardenobserver"
55

66
import (
7+
"errors"
8+
"fmt"
79
"time"
810
)
911

1012
// Config defines configuration for CF Garden observer.
1113
type Config struct {
12-
// The URL of the CF Garden api. Default is "unix:///var/vcap/data/garden/garden.sock"
13-
Endpoint string `mapstructure:"endpoint"`
14+
// CloudFoundry API Configuration
15+
CloudFoundry CfConfig `mapstructure:"cloud_foundry"`
16+
17+
// Garden API Configuration
18+
Garden GardenConfig `mapstructure:"garden"`
1419

1520
// RefreshInterval determines the frequency at which the observer
1621
// needs to poll for collecting information about new processes.
22+
// Default: "1m"
1723
RefreshInterval time.Duration `mapstructure:"refresh_interval"`
24+
25+
// The time to wait before resyncing app information on cached containers
26+
// using the CloudFoundry API.
27+
// Default: "5m"
28+
CacheSyncInterval time.Duration `mapstructure:"cache_sync_interval"`
29+
30+
// Determines whether or not Application labels get added to the Endpoint labels.
31+
// This requires cloud_foundry to be configured, such that API calls can be made
32+
// Default: false
33+
IncludeAppLabels bool `mapstructure:"include_app_labels"`
34+
}
35+
36+
// Validate overrides the embedded noop validation so that load config can trigger
37+
// our own validation logic.
38+
func (config *Config) Validate() error {
39+
if !config.IncludeAppLabels {
40+
return nil
41+
}
42+
43+
c := config.CloudFoundry
44+
if c.Endpoint == "" {
45+
return errors.New("CloudFoundry.Endpoint must be specified when IncludeAppLabels is set to true")
46+
}
47+
if c.Auth.Type == "" {
48+
return errors.New("CloudFoundry.Auth.Type must be specified when IncludeAppLabels is set to true")
49+
}
50+
51+
switch c.Auth.Type {
52+
case authTypeUserPass:
53+
if c.Auth.Username == "" {
54+
return fieldError(authTypeUserPass, "username")
55+
}
56+
if c.Auth.Password == "" {
57+
return fieldError(authTypeUserPass, "password")
58+
}
59+
case authTypeClientCredentials:
60+
if c.Auth.ClientID == "" {
61+
return fieldError(authTypeClientCredentials, "client_id")
62+
}
63+
if c.Auth.ClientSecret == "" {
64+
return fieldError(authTypeClientCredentials, "client_secret")
65+
}
66+
case authTypeToken:
67+
if c.Auth.AccessToken == "" {
68+
return fieldError(authTypeToken, "access_token")
69+
}
70+
if c.Auth.RefreshToken == "" {
71+
return fieldError(authTypeToken, "refresh_token")
72+
}
73+
default:
74+
return fmt.Errorf("configuration option `auth_type` must be set to one of the following values: [user_pass, client_credentials, token]. Specified value: %s", c.Auth.Type)
75+
}
76+
77+
return nil
78+
}
79+
80+
func fieldError(authType authType, param string) error {
81+
return fmt.Errorf("%s is required when using auth_type: %s", param, authType)
82+
}
83+
84+
type GardenConfig struct {
85+
// The URL of the CF Garden api. Default is "/var/vcap/data/garden/garden.sock"
86+
Endpoint string `mapstructure:"endpoint"`
1887
}
88+
89+
type CfConfig struct {
90+
// The URL of the CloudFoundry API
91+
Endpoint string `mapstructure:"endpoint"`
92+
93+
// Authentication details
94+
Auth CfAuth `mapstructure:"auth"`
95+
}
96+
97+
type CfAuth struct {
98+
// Authentication method, there are 3 options
99+
Type authType `mapstructure:"type"`
100+
101+
// Used for user_pass authentication method
102+
Username string `mapstructure:"username"`
103+
Password string `mapstructure:"password"`
104+
105+
// Used for token authentication method
106+
AccessToken string `mapstructure:"access_token"`
107+
RefreshToken string `mapstructure:"refresh_token"`
108+
109+
// Used for client_credentials authentication method
110+
ClientID string `mapstructure:"client_id"`
111+
ClientSecret string `mapstructure:"client_secret"`
112+
}
113+
114+
// authType describes the type of authentication to use for the CloudFoundry API
115+
type authType string
116+
117+
const (
118+
// authTypeClientCredentials uses a client ID and client secret to authenticate
119+
authTypeClientCredentials authType = "client_credentials"
120+
// authTypeUserPass uses username and password to authenticate
121+
authTypeUserPass authType = "user_pass"
122+
// authTypeToken uses access token and refresh token to authenticate
123+
authTypeToken authType = "token"
124+
)

0 commit comments

Comments
 (0)