Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Add checks for selectors in KubernetesSDConfig (#6177) #6359

Merged
merged 1 commit into from
Apr 3, 2024

Conversation

yp969803
Copy link
Contributor

@yp969803 yp969803 commented Mar 2, 2024

Description

fix: #6177
additional checks on the role selectors vs. the main role added

Type of change

What type of changes does your code introduce to the Prometheus operator? Put an x in the box that apply.

  • CHANGE (fix or feature that would cause existing functionality to not work as expected)
  • FEATURE (non-breaking change which adds functionality)
  • BUGFIX (non-breaking change which fixes an issue)
  • ENHANCEMENT (non-breaking change which improves existing functionality)
  • NONE (if none of the other choices apply. Example, tooling, build system, CI, docs, etc.)

Changelog entry

Add checks for selectors in KubernetesSDConfig

@yp969803 yp969803 requested a review from a team as a code owner March 2, 2024 18:37
@yp969803
Copy link
Contributor Author

yp969803 commented Mar 2, 2024

@slashpai can you review the pr

Copy link
Contributor

@slashpai slashpai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't reviewed full but its a good start, could you please add a test as well in https://github.com/prometheus-operator/prometheus-operator/blob/main/pkg/prometheus/resource_selector_test.go#L1710?

@@ -354,6 +366,32 @@ type KubernetesSDConfig struct {
Selectors []K8SSelectorConfig `json:"selectors,omitempty"`
}

// ValidateSelectorRoles validate the roles based on main role.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -2604,6 +2604,12 @@ func (cg *ConfigGenerator) generateScrapeConfig(
if len(sc.Spec.KubernetesSDConfigs) > 0 {
configs := make([][]yaml.MapItem, len(sc.Spec.KubernetesSDConfigs))
for i, config := range sc.Spec.KubernetesSDConfigs {

err := (&config).ValidateSelectorRoles()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yp969803
Copy link
Contributor Author

yp969803 commented Mar 5, 2024

@slashpai done the changes and added the tests

Comment on lines 846 to 860
foundSelectorRoles := make(map[monitoringv1alpha1.Role]struct{})
allowedSelectors := map[monitoringv1alpha1.Role][]string{
RolePod: {string(RolePod)},
RoleService: {string(RoleService)},
RoleEndpointSlice: {string(RolePod), string(RoleService), string(RoleEndpointSlice)},
RoleEndpoint: {string(RolePod), string(RoleService), string(RoleEndpoint)},
RoleNode: {string(RoleNode)},
RoleIngress: {string(RoleIngress)},
}

for _, selector := range c.Selectors {

if _, ok := foundSelectorRoles[selector.Role]; ok {
return fmt.Errorf("duplicated selector role: %s", selector.Role)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the impression that foundSelectorRoles is never populated, therefore line 858 will never return ok 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it returns ok then error will come, while if it returns !ok then it should pass, tests are also passing

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Arthur, I also tried it as a simple go code here https://go.dev/play/p/Di7AaLX_iW-
currently it accepts the the role pod for role node which it shouldn't.

Take a look at validation here we need to do something similar https://github.com/prometheus/prometheus/blob/92544c00bf9d43eecd7161911d541a3fbe7af8cc/discovery/kubernetes/kubernetes.go#L204-L233

Copy link
Contributor

@slashpai slashpai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you also test this it locally on a cluster?

@@ -2604,6 +2604,7 @@ func (cg *ConfigGenerator) generateScrapeConfig(
if len(sc.Spec.KubernetesSDConfigs) > 0 {
configs := make([][]yaml.MapItem, len(sc.Spec.KubernetesSDConfigs))
for i, config := range sc.Spec.KubernetesSDConfigs {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove the blank line

@@ -830,13 +840,38 @@ func (rs *ResourceSelector) SelectScrapeConfigs(ctx context.Context, listFn List
return res, nil
}

// ValidateSelectorRoles validate the roles based on main role.
func ValidateSelectorRoles(c monitoringv1alpha1.KubernetesSDConfig) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to have a function for this as it is not used any other place, better lets move the code to

func (rs *ResourceSelector) validateKubernetesSDConfigs(ctx context.Context, sc *monitoringv1alpha1.ScrapeConfig) error {
for i, config := range sc.Spec.KubernetesSDConfigs {
configKey := fmt.Sprintf("scrapeconfig/%s/%s/kubernetessdconfig/%d", sc.GetNamespace(), sc.GetName(), i)
if err := rs.store.AddBasicAuth(ctx, sc.GetNamespace(), config.BasicAuth, configKey); err != nil {
return fmt.Errorf("[%d]: %w", i, err)
}
configAuthKey := fmt.Sprintf("scrapeconfig/auth/%s/%s/kubernetessdconfig/%d", sc.GetNamespace(), sc.GetName(), i)
if err := rs.store.AddSafeAuthorizationCredentials(ctx, sc.GetNamespace(), config.Authorization, configAuthKey); err != nil {
return fmt.Errorf("[%d]: %w", i, err)
}
if err := rs.store.AddOAuth2(ctx, sc.GetNamespace(), config.OAuth2, configKey); err != nil {
return fmt.Errorf("[%d]: %w", i, err)
}
if err := rs.store.AddSafeTLSConfig(ctx, sc.GetNamespace(), config.TLSConfig); err != nil {
return fmt.Errorf("[%d]: %w", i, err)
}
if err := validateProxyConfig(ctx, config.ProxyConfig, rs.store, sc.GetNamespace()); err != nil {
return fmt.Errorf("[%d]: %w", i, err)
}
if config.APIServer != nil && config.Namespaces != nil {
if ptr.Deref(config.Namespaces.IncludeOwnNamespace, false) {
return fmt.Errorf("[%d]: %w", i, errors.New("cannot use 'apiServer' and 'namespaces.ownNamespace' simultaneously"))
}
}
for _, s := range config.Selectors {

Comment on lines 846 to 860
foundSelectorRoles := make(map[monitoringv1alpha1.Role]struct{})
allowedSelectors := map[monitoringv1alpha1.Role][]string{
RolePod: {string(RolePod)},
RoleService: {string(RoleService)},
RoleEndpointSlice: {string(RolePod), string(RoleService), string(RoleEndpointSlice)},
RoleEndpoint: {string(RolePod), string(RoleService), string(RoleEndpoint)},
RoleNode: {string(RoleNode)},
RoleIngress: {string(RoleIngress)},
}

for _, selector := range c.Selectors {

if _, ok := foundSelectorRoles[selector.Role]; ok {
return fmt.Errorf("duplicated selector role: %s", selector.Role)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Arthur, I also tried it as a simple go code here https://go.dev/play/p/Di7AaLX_iW-
currently it accepts the the role pod for role node which it shouldn't.

Take a look at validation here we need to do something similar https://github.com/prometheus/prometheus/blob/92544c00bf9d43eecd7161911d541a3fbe7af8cc/discovery/kubernetes/kubernetes.go#L204-L233

}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove extra blank line

@@ -870,7 +909,9 @@ func (rs *ResourceSelector) validateKubernetesSDConfigs(ctx context.Context, sc
if _, err := labels.Parse(s.Label); err != nil {
return fmt.Errorf("[%d]: %w", i, err)
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove extra blank line


for _, selector := range c.Selectors {

if _, ok := foundSelectorRoles[selector.Role]; ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to apply strings.ToLower() on the role value (e.g. prometheus-operator both "Pod" and "pod").

@yp969803
Copy link
Contributor Author

@slashpai done the changes

@@ -42,6 +42,16 @@ import (
"github.com/prometheus-operator/prometheus-operator/pkg/operator"
)

// The valid options for Role.
const (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be good to have the consts defined in pkg/apis/monitoring/v1 directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@simonpasquier previously i have done the same, but @slashpai suggested me to put it in the resource_selector

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thats for validation methods 🙂
Since consts were also moved I was ok but I agree with Simon consts go better in types.go

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's have a follow-up for this.

Comment on lines 888 to 889
var allowed bool

for _, role := range allowedSelectors[config.Role] {
if role == strings.ToLower(string(s.Role)) {
allowed = true
break
}
}
if !allowed {
return fmt.Errorf("[%d] : %s role supports only %s selectors", i, config.Role, strings.Join(allowedSelectors[config.Role], ", "))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(suggestion) we could use https://pkg.go.dev/slices#Contains

}

for _, s := range config.Selectors {
if _, ok := allowedSelectors[config.Role]; !ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need strings.ToLower too?

Suggested change
if _, ok := allowedSelectors[config.Role]; !ok {
if _, ok := allowedSelectors[strings.ToLower(config.Role)]; !ok {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -42,6 +42,16 @@ import (
"github.com/prometheus-operator/prometheus-operator/pkg/operator"
)

// The valid options for Role.
const (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's have a follow-up for this.

@simonpasquier
Copy link
Contributor

TestSelectScrapeConfigs/Kubernetes_SD_config_with_valid_label_and_field_selectors is failing

…rator#6177)

chore: test added

rfac: kubernetes sd role

chore: cofig.Role to lowercase

rfac: unit_test role_consts
@yp969803
Copy link
Contributor Author

yp969803 commented Apr 2, 2024

@simonpasquier done the above changes, rfac the unit test

Copy link
Contributor

@simonpasquier simonpasquier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@slashpai slashpai merged commit 745813d into prometheus-operator:main Apr 3, 2024
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ScrapeConfig/KubernetesSDConfig: Add checks for selectors
4 participants