Skip to content

Commit 3035243

Browse files
committed
Implement capabilities list via reflection
1 parent 97865ae commit 3035243

8 files changed

Lines changed: 217 additions & 98 deletions

File tree

internal/providers/dockerhub/metadata.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,20 @@ package dockerhub
55

66
import (
77
minderv1 "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1"
8+
provifv1 "github.com/mindersec/minder/pkg/providers/v1"
89
)
910

1011
const (
1112
providerDocsBaseURL = "https://docs.mindersec.dev"
1213
providerDocsURL = providerDocsBaseURL + "/understand/providers"
1314
)
1415

15-
// ClassInfo returns metadata for the Docker Hub provider class.
16-
func ClassInfo() *minderv1.ProviderClassInfo {
16+
func (d *dockerHubImageLister) ProviderClassInfo() *minderv1.ProviderClassInfo {
1717
return &minderv1.ProviderClassInfo{
18-
Class: DockerHub,
19-
DisplayName: "Docker Hub",
20-
Description: "Docker Hub registry provider for image and OCI interactions.",
21-
SupportedProviderTypes: []minderv1.ProviderType{
22-
minderv1.ProviderType_PROVIDER_TYPE_IMAGE_LISTER,
23-
minderv1.ProviderType_PROVIDER_TYPE_OCI,
24-
},
18+
Class: DockerHub,
19+
DisplayName: "Docker Hub",
20+
Description: "Docker Hub registry provider for image and OCI interactions.",
21+
SupportedProviderTypes: provifv1.ProviderTypesFromImpl(d),
2522
SupportedAuthFlows: []minderv1.AuthorizationFlow{
2623
minderv1.AuthorizationFlow_AUTHORIZATION_FLOW_USER_INPUT,
2724
},
@@ -30,6 +27,8 @@ func ClassInfo() *minderv1.ProviderClassInfo {
3027
}
3128
}
3229

33-
func (*dockerHubImageLister) ProviderClassInfo() *minderv1.ProviderClassInfo {
34-
return ClassInfo()
30+
// ClassInfo returns metadata for the Docker Hub provider class.
31+
// It uses a nil-pointer receiver to avoid needing a live client instance.
32+
func ClassInfo() *minderv1.ProviderClassInfo {
33+
return (*dockerHubImageLister)(nil).ProviderClassInfo()
3534
}

internal/providers/dockerhub/provider_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ package dockerhub
66
import (
77
"testing"
88

9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
12+
minderv1 "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1"
913
testhelper "github.com/mindersec/minder/pkg/providers/v1/testing"
1014
)
1115

@@ -15,3 +19,26 @@ func TestRegistration(t *testing.T) {
1519
dh := &dockerHubImageLister{}
1620
testhelper.CheckRegistrationExcept(t, dh)
1721
}
22+
23+
func TestClassInfo(t *testing.T) {
24+
t.Parallel()
25+
26+
info := ClassInfo()
27+
require.NotNil(t, info)
28+
29+
assert.Equal(t, DockerHub, info.Class)
30+
assert.Equal(t, "Docker Hub", info.DisplayName)
31+
assert.NotEmpty(t, info.Description)
32+
assert.Equal(t, providerDocsURL, info.DocumentationUrl)
33+
34+
assert.ElementsMatch(t, []minderv1.AuthorizationFlow{
35+
minderv1.AuthorizationFlow_AUTHORIZATION_FLOW_USER_INPUT,
36+
}, info.SupportedAuthFlows)
37+
38+
assert.Empty(t, info.SupportedEntities)
39+
40+
assert.ElementsMatch(t, []minderv1.ProviderType{
41+
minderv1.ProviderType_PROVIDER_TYPE_IMAGE_LISTER,
42+
minderv1.ProviderType_PROVIDER_TYPE_OCI,
43+
}, info.SupportedProviderTypes)
44+
}

internal/providers/github/clients/app.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ import (
2626
// GithubApp is the string that represents the GitHubApp provider
2727
const GithubApp = "github-app"
2828

29-
// AppImplements is the list of provider types that the GitHub App provider implements.
30-
var AppImplements = github.AppImplements
31-
3229
// AppAuthorizationFlows is the list of authorization flows that the GitHub App provider supports.
3330
var AppAuthorizationFlows = github.AppAuthorizationFlows
3431

internal/providers/github/metadata.go

Lines changed: 26 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -8,114 +8,68 @@ import (
88

99
"github.com/mindersec/minder/internal/db"
1010
minderv1 "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1"
11+
provifv1 "github.com/mindersec/minder/pkg/providers/v1"
1112
)
1213

1314
const (
1415
providerDocsBaseURL = "https://docs.mindersec.dev"
1516
providerDocsURL = providerDocsBaseURL + "/integrations/provider_integrations/github"
1617
)
1718

18-
// OAuthImplements is the list of provider types that the GitHub OAuth provider implements.
19-
var OAuthImplements = []db.ProviderType{
20-
db.ProviderTypeGithub,
21-
db.ProviderTypeGit,
22-
db.ProviderTypeRest,
23-
db.ProviderTypeRepoLister,
24-
}
25-
2619
// OAuthAuthorizationFlows is the list of authorization flows that the GitHub OAuth provider supports.
2720
var OAuthAuthorizationFlows = []db.AuthorizationFlow{
2821
db.AuthorizationFlowUserInput,
2922
db.AuthorizationFlowOauth2AuthorizationCodeFlow,
3023
}
3124

32-
// AppImplements is the list of provider types that the GitHub App provider implements.
33-
var AppImplements = []db.ProviderType{
34-
db.ProviderTypeGithub,
35-
db.ProviderTypeGit,
36-
db.ProviderTypeRest,
37-
db.ProviderTypeRepoLister,
38-
}
39-
4025
// AppAuthorizationFlows is the list of authorization flows that the GitHub App provider supports.
4126
var AppAuthorizationFlows = []db.AuthorizationFlow{
4227
db.AuthorizationFlowGithubAppFlow,
4328
}
4429

45-
// ProviderClassInfo returns class metadata for GitHub-backed provider classes.
46-
func ProviderClassInfo(class db.ProviderClass) (*minderv1.ProviderClassInfo, error) {
47-
switch class {
30+
// ProviderClassInfo implements the Provider interface.
31+
func (c *GitHub) ProviderClassInfo() *minderv1.ProviderClassInfo {
32+
supportedTypes := provifv1.ProviderTypesFromImpl(c)
33+
supportedEntities := []minderv1.Entity{
34+
minderv1.Entity_ENTITY_REPOSITORIES,
35+
minderv1.Entity_ENTITY_PULL_REQUESTS,
36+
minderv1.Entity_ENTITY_ARTIFACTS,
37+
minderv1.Entity_ENTITY_RELEASE,
38+
}
39+
switch c.providerClass {
4840
case db.ProviderClassGithub:
4941
return &minderv1.ProviderClassInfo{
5042
Class: string(db.ProviderClassGithub),
5143
DisplayName: "GitHub OAuth",
5244
Description: "GitHub provider using OAuth credentials.",
53-
SupportedProviderTypes: dbProviderTypesToPB(OAuthImplements),
45+
SupportedProviderTypes: supportedTypes,
5446
SupportedAuthFlows: dbAuthFlowsToPB(OAuthAuthorizationFlows),
55-
SupportedEntities: []minderv1.Entity{
56-
minderv1.Entity_ENTITY_REPOSITORIES,
57-
minderv1.Entity_ENTITY_PULL_REQUESTS,
58-
minderv1.Entity_ENTITY_ARTIFACTS,
59-
minderv1.Entity_ENTITY_RELEASE,
60-
},
61-
DocumentationUrl: providerDocsURL,
62-
}, nil
47+
SupportedEntities: supportedEntities,
48+
DocumentationUrl: providerDocsURL,
49+
}
6350
case db.ProviderClassGithubApp:
6451
return &minderv1.ProviderClassInfo{
6552
Class: string(db.ProviderClassGithubApp),
6653
DisplayName: "GitHub App",
6754
Description: "GitHub App-based provider with installation-based authorization.",
68-
SupportedProviderTypes: dbProviderTypesToPB(AppImplements),
55+
SupportedProviderTypes: supportedTypes,
6956
SupportedAuthFlows: dbAuthFlowsToPB(AppAuthorizationFlows),
70-
SupportedEntities: []minderv1.Entity{
71-
minderv1.Entity_ENTITY_REPOSITORIES,
72-
minderv1.Entity_ENTITY_PULL_REQUESTS,
73-
minderv1.Entity_ENTITY_ARTIFACTS,
74-
minderv1.Entity_ENTITY_RELEASE,
75-
},
76-
DocumentationUrl: providerDocsURL,
77-
}, nil
78-
case db.ProviderClassGhcr:
79-
fallthrough
80-
case db.ProviderClassDockerhub:
81-
fallthrough
82-
case db.ProviderClassGitlab:
83-
return nil, fmt.Errorf("unsupported GitHub provider class: %s", class)
57+
SupportedEntities: supportedEntities,
58+
DocumentationUrl: providerDocsURL,
59+
}
8460
default:
85-
return nil, fmt.Errorf("unsupported GitHub provider class: %s", class)
86-
}
87-
}
88-
89-
// ProviderClassInfo implements the Provider interface.
90-
func (c *GitHub) ProviderClassInfo() *minderv1.ProviderClassInfo {
91-
info, err := ProviderClassInfo(c.providerClass)
92-
if err != nil {
9361
return nil
9462
}
95-
96-
return info
9763
}
9864

99-
func dbProviderTypesToPB(types []db.ProviderType) []minderv1.ProviderType {
100-
out := make([]minderv1.ProviderType, 0, len(types))
101-
for _, t := range types {
102-
switch t {
103-
case db.ProviderTypeGit:
104-
out = append(out, minderv1.ProviderType_PROVIDER_TYPE_GIT)
105-
case db.ProviderTypeGithub:
106-
out = append(out, minderv1.ProviderType_PROVIDER_TYPE_GITHUB)
107-
case db.ProviderTypeRest:
108-
out = append(out, minderv1.ProviderType_PROVIDER_TYPE_REST)
109-
case db.ProviderTypeRepoLister:
110-
out = append(out, minderv1.ProviderType_PROVIDER_TYPE_REPO_LISTER)
111-
case db.ProviderTypeOci:
112-
out = append(out, minderv1.ProviderType_PROVIDER_TYPE_OCI)
113-
case db.ProviderTypeImageLister:
114-
out = append(out, minderv1.ProviderType_PROVIDER_TYPE_IMAGE_LISTER)
115-
}
65+
// ProviderClassInfo returns class metadata for GitHub-backed provider classes.
66+
// It uses a nil-pointer receiver to avoid needing a live client instance.
67+
func ProviderClassInfo(class db.ProviderClass) (*minderv1.ProviderClassInfo, error) {
68+
info := (&GitHub{providerClass: class}).ProviderClassInfo()
69+
if info == nil {
70+
return nil, fmt.Errorf("unsupported GitHub provider class: %s", class)
11671
}
117-
118-
return out
72+
return info, nil
11973
}
12074

12175
func dbAuthFlowsToPB(flows []db.AuthorizationFlow) []minderv1.AuthorizationFlow {

internal/providers/github/provider_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44
package github
55

66
import (
7+
"slices"
78
"testing"
89

10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/mindersec/minder/internal/db"
914
"github.com/mindersec/minder/internal/providers/github/properties"
1015
minderv1 "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1"
1116
testhelper "github.com/mindersec/minder/pkg/providers/v1/testing"
@@ -21,3 +26,75 @@ func TestRegistration(t *testing.T) {
2126
// in this test -- we test them in common_test.go.
2227
testhelper.CheckRegistrationExcept(t, gh, minderv1.Entity_ENTITY_REPOSITORIES)
2328
}
29+
30+
func TestProviderClassInfo(t *testing.T) {
31+
t.Parallel()
32+
33+
wantEntities := []minderv1.Entity{
34+
minderv1.Entity_ENTITY_REPOSITORIES,
35+
minderv1.Entity_ENTITY_PULL_REQUESTS,
36+
minderv1.Entity_ENTITY_ARTIFACTS,
37+
minderv1.Entity_ENTITY_RELEASE,
38+
}
39+
wantTypes := []minderv1.ProviderType{
40+
minderv1.ProviderType_PROVIDER_TYPE_GITHUB,
41+
minderv1.ProviderType_PROVIDER_TYPE_GIT,
42+
minderv1.ProviderType_PROVIDER_TYPE_REST,
43+
minderv1.ProviderType_PROVIDER_TYPE_REPO_LISTER,
44+
minderv1.ProviderType_PROVIDER_TYPE_IMAGE_LISTER,
45+
}
46+
47+
tests := []struct {
48+
name string
49+
providerClass db.ProviderClass
50+
wantClass string
51+
wantDisplay string
52+
wantAuthFlows []minderv1.AuthorizationFlow
53+
}{
54+
{
55+
name: "GitHub OAuth",
56+
providerClass: db.ProviderClassGithub,
57+
wantClass: string(db.ProviderClassGithub),
58+
wantDisplay: "GitHub OAuth",
59+
wantAuthFlows: []minderv1.AuthorizationFlow{
60+
minderv1.AuthorizationFlow_AUTHORIZATION_FLOW_USER_INPUT,
61+
minderv1.AuthorizationFlow_AUTHORIZATION_FLOW_OAUTH2_AUTHORIZATION_CODE_FLOW,
62+
},
63+
},
64+
{
65+
name: "GitHub App",
66+
providerClass: db.ProviderClassGithubApp,
67+
wantClass: string(db.ProviderClassGithubApp),
68+
wantDisplay: "GitHub App",
69+
wantAuthFlows: []minderv1.AuthorizationFlow{
70+
minderv1.AuthorizationFlow_AUTHORIZATION_FLOW_GITHUB_APP_FLOW,
71+
},
72+
},
73+
}
74+
75+
for _, tt := range tests {
76+
t.Run(tt.name, func(t *testing.T) {
77+
t.Parallel()
78+
gh := &GitHub{
79+
propertyFetchers: properties.NewPropertyFetcherFactory(),
80+
providerClass: tt.providerClass,
81+
}
82+
83+
info := gh.ProviderClassInfo()
84+
require.NotNil(t, info)
85+
86+
assert.Equal(t, tt.wantClass, info.Class)
87+
assert.Equal(t, tt.wantDisplay, info.DisplayName)
88+
assert.NotEmpty(t, info.Description)
89+
assert.Equal(t, providerDocsURL, info.DocumentationUrl)
90+
91+
assert.ElementsMatch(t, tt.wantAuthFlows, info.SupportedAuthFlows)
92+
assert.ElementsMatch(t, wantEntities, info.SupportedEntities)
93+
94+
for _, want := range wantTypes {
95+
assert.True(t, slices.Contains(info.SupportedProviderTypes, want),
96+
"expected SupportedProviderTypes to contain %v", want)
97+
}
98+
})
99+
}
100+
}

internal/providers/gitlab/metadata.go

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,20 @@ package gitlab
55

66
import (
77
minderv1 "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1"
8+
provifv1 "github.com/mindersec/minder/pkg/providers/v1"
89
)
910

1011
const (
1112
providerDocsBaseURL = "https://docs.mindersec.dev"
1213
providerDocsURL = providerDocsBaseURL + "/understand/providers"
1314
)
1415

15-
// ClassInfo returns metadata for the GitLab provider class.
16-
func ClassInfo() *minderv1.ProviderClassInfo {
16+
func (c *gitlabClient) ProviderClassInfo() *minderv1.ProviderClassInfo {
1717
return &minderv1.ProviderClassInfo{
18-
Class: Class,
19-
DisplayName: "GitLab",
20-
Description: "GitLab provider using OAuth credentials.",
21-
SupportedProviderTypes: []minderv1.ProviderType{
22-
minderv1.ProviderType_PROVIDER_TYPE_GIT,
23-
minderv1.ProviderType_PROVIDER_TYPE_REST,
24-
minderv1.ProviderType_PROVIDER_TYPE_REPO_LISTER,
25-
},
18+
Class: Class,
19+
DisplayName: "GitLab",
20+
Description: "GitLab provider using OAuth credentials.",
21+
SupportedProviderTypes: provifv1.ProviderTypesFromImpl(c),
2622
SupportedAuthFlows: []minderv1.AuthorizationFlow{
2723
minderv1.AuthorizationFlow_AUTHORIZATION_FLOW_USER_INPUT,
2824
minderv1.AuthorizationFlow_AUTHORIZATION_FLOW_OAUTH2_AUTHORIZATION_CODE_FLOW,
@@ -36,6 +32,8 @@ func ClassInfo() *minderv1.ProviderClassInfo {
3632
}
3733
}
3834

39-
func (*gitlabClient) ProviderClassInfo() *minderv1.ProviderClassInfo {
40-
return ClassInfo()
35+
// ClassInfo returns metadata for the GitLab provider class.
36+
// It uses a nil-pointer receiver to avoid needing a live client instance.
37+
func ClassInfo() *minderv1.ProviderClassInfo {
38+
return (*gitlabClient)(nil).ProviderClassInfo()
4139
}

0 commit comments

Comments
 (0)