Skip to content

Commit 3b6785a

Browse files
committed
fix(tasks): locate v2 components by their def file's content, not just its name
comp/core/delegatedauth/def/delegatedauth.go was silently invisible to components.lint-components because locate_component_def only recognized 'def/component.go' by exact filename. This meant its `// team: core-authn` tag never made it into CODEOWNERS, and the component fell back to its parent bundle's owner (agent-runtimes) instead. locate_component_def now falls back to scanning 'def/' for a Go file defining the Component interface, and check_component_contents_and_file_hiearchy reports an explicit lint error when that file isn't named 'component.go', so a misnamed def file is now caught instead of silently dropped.
1 parent 0ae6987 commit 3b6785a

6 files changed

Lines changed: 65 additions & 3 deletions

File tree

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@
409409
/comp/core/configstream @DataDog/fleet-automation
410410
/comp/core/configstreamconsumer @DataDog/fleet-automation
411411
/comp/core/configsync @DataDog/fleet-automation
412+
/comp/core/delegatedauth @DataDog/core-authn
412413
/comp/core/diagnose @DataDog/fleet-remediation
413414
/comp/core/flare @DataDog/fleet-remediation
414415
/comp/core/gui @DataDog/fleet-remediation

comp/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ Package configstreamconsumer implements a component that consumes config streams
140140

141141
Package configsync implements synchronizing the configuration using the core agent config API
142142

143+
### [comp/core/delegatedauth](https://pkg.go.dev/github.com/DataDog/datadog-agent/comp/core/delegatedauth)
144+
145+
*Datadog Team*: core-authn
146+
147+
Package delegatedauth manages cloud-based delegated authentication for the agent.
148+
143149
### [comp/core/diagnose](https://pkg.go.dev/github.com/DataDog/datadog-agent/comp/core/diagnose)
144150

145151
*Datadog Team*: fleet-remediation

comp/core/delegatedauth/def/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ load("@rules_go//go:def.bzl", "go_library")
22

33
go_library(
44
name = "def",
5-
srcs = ["delegatedauth.go"],
5+
srcs = ["component.go"],
66
importpath = "github.com/DataDog/datadog-agent/comp/core/delegatedauth/def",
77
visibility = ["//visibility:public"],
88
deps = [
File renamed without changes.

tasks/components.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ def check_component_contents_and_file_hiearchy(comp):
169169
if comp.def_file == 'comp/api/api/def/component.go':
170170
return
171171

172+
# Definition file must be named 'component.go' for v2 components. This is found by content
173+
# (its 'type Component' definition) rather than by name, so a wrongly-named file is reported
174+
# here instead of silently failing to be recognized as the component's definition.
175+
if comp.version == 2 and pathlib.Path(comp.def_file).name != 'component.go':
176+
return f"** {comp.def_file} should be renamed to 'component.go'. See https://datadoghq.dev/datadog-agent/components/creating-components/"
177+
172178
# Definition file `component.go` (v1) or `def/component.go` (v2) must use `package <compname>`
173179
pkgname = parse_package_name(comp.def_file)
174180
if pkgname != comp.name:
@@ -369,15 +375,40 @@ def get_components_and_bundles():
369375
return sorted(components, key=lambda c: c.path), sorted(sorted_bundles, key=lambda b: b.path)
370376

371377

378+
def find_component_def_file(def_dir):
379+
"""
380+
Return the Go file in def_dir that defines the Component interface, if any.
381+
382+
Components are expected to name this file 'component.go' (checked separately in
383+
check_component_contents_and_file_hiearchy), but we locate it here by content so that a
384+
misnamed file still gets picked up as a component - and reported with an actionable error -
385+
instead of silently vanishing from component/codeowners generation.
386+
"""
387+
for entry in sorted(def_dir.iterdir()):
388+
if not entry.is_file() or not entry.name.endswith('.go') or entry.name.endswith('_test.go'):
389+
continue
390+
content = read_file_content(entry).split('\n')
391+
if any(line.startswith('type Component interface') or line.startswith('type Component = ') for line in content):
392+
return entry
393+
394+
return None
395+
396+
372397
def locate_component_def(dir):
373398
"""
374399
Locate the component, if this directory contains a component
375400
"""
376401
component_name = dir.name.replace('-', '').lower()
377402

378-
# v2 component: this folder is a component root if it contains 'def/component.go'
403+
# v2 component: this folder is a component root if it contains 'def/component.go', or, failing
404+
# that, another Go file in 'def' that defines the Component interface (see find_component_def_file)
379405
def_file = dir / 'def/component.go'
380-
if def_file.is_file():
406+
if not def_file.is_file():
407+
def_subdir = dir / 'def'
408+
if def_subdir.is_dir():
409+
def_file = find_component_def_file(def_subdir)
410+
411+
if def_file is not None and def_file.is_file():
381412
# comp/api/api/def/component.go is a special case, it's not a component using version 2
382413
# PLEASE DO NOT ADD MORE EXCEPTIONS
383414
if to_posix_path(def_file) == "comp/api/api/def/component.go":

tasks/unit_tests/components_tests.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ def test_locate_root(self):
6161
root = components.locate_component_def(Path('comp/newstyle'))
6262
self.assertEqual(2, root.version)
6363

64+
def test_locate_root_misnamed_def_file(self):
65+
# A def/component.go file that isn't named 'component.go' should still be located as the
66+
# component's definition file (by its 'type Component' definition), rather than silently
67+
# not being recognized as a component at all.
68+
oldfilename = os.path.join('comp/newstyle', 'def/component.go')
69+
newfilename = os.path.join('comp/newstyle', 'def/newstyle.go')
70+
shutil.move(oldfilename, newfilename)
71+
72+
root = components.locate_component_def(Path('comp/newstyle'))
73+
self.assertEqual(2, root.version)
74+
self.assertEqual(components.to_posix_path(newfilename), root.def_file)
75+
6476
def test_validate_bundles(self):
6577
_, bundles = components.get_components_and_bundles()
6678
errs = components.validate_bundles(bundles)
@@ -137,6 +149,18 @@ def test_validate_component_definition(self):
137149
self.assertEqual(1, len(errs))
138150
self.assertIn('separate implementation', errs[0])
139151

152+
# Lint error because def/component.go should be named 'component.go'
153+
self.reset_component_src_in_tmpdir()
154+
155+
oldfilename = os.path.join(comps[3].path, 'def/component.go')
156+
newfilename = os.path.join(comps[3].path, 'def/newstyle.go')
157+
shutil.move(oldfilename, newfilename)
158+
159+
comps, _ = components.get_components_and_bundles()
160+
errs = components.validate_components(comps)
161+
self.assertEqual(1, len(errs))
162+
self.assertIn("should be renamed to 'component.go'", errs[0])
163+
140164
def test_validate_component_fx(self):
141165
comps, _ = components.get_components_and_bundles()
142166
errs = components.validate_components(comps)

0 commit comments

Comments
 (0)