Skip to content

Commit 9831552

Browse files
authored
Merge pull request #1 from fluxcd/add_interfaces_types
Add the GitProvider Client interfaces and types
2 parents 6745981 + dd446b3 commit 9831552

20 files changed

+3338
-0
lines changed

.github/workflows/golangci.yaml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# https://github.com/marketplace/actions/run-golangci-lint
2+
name: golangci-lint
3+
on: [push, pull_request]
4+
jobs:
5+
golangci:
6+
name: lint
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
- name: golangci-lint
11+
uses: golangci/golangci-lint-action@v1
12+
with:
13+
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
14+
version: v1.28

MAINTAINERS

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ https://cloud-native.slack.com in #flux (https://cloud-native.slack.com/messages
44

55
In alphabetical order:
66

7+
Lucas Käldström, Weaveworks <[email protected]> (github: @luxas, slack: luxas)
78
Stefan Prodan, Weaveworks <[email protected]> (github: @stefanprodan, slack: stefanprodan)

client.go

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/*
2+
Copyright 2020 The Flux CD contributors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package gitprovider
18+
19+
import "context"
20+
21+
// Client is an interface that allows talking to a Git provider
22+
type Client interface {
23+
// The Client allows accessing all known resources
24+
ResourceClient
25+
26+
// SupportedDomain returns the domain endpoint for this client, e.g. "github.com", "gitlab.com" or
27+
// "my-custom-git-server.com:6443". This allows a higher-level user to know what Client to use for
28+
// what endpoints.
29+
// This field is set at client creation time, and can't be changed
30+
SupportedDomain() string
31+
32+
// ProviderID returns the provider ID (e.g. "github", "gitlab") for this client
33+
// This field is set at client creation time, and can't be changed
34+
ProviderID() ProviderID
35+
36+
// Raw returns the Go client used under the hood for accessing the Git provider
37+
Raw() interface{}
38+
}
39+
40+
// ResourceClient allows access to resource-specific clients
41+
type ResourceClient interface {
42+
// Organization gets the OrganizationClient for the specific top-level organization, or user account.
43+
// ErrNotTopLevelOrganization will be returned if the organization is not top-level
44+
Organization(o OrganizationRef) OrganizationClient
45+
46+
// Organizations returns the OrganizationsClient handling sets of organizations
47+
Organizations() OrganizationsClient
48+
49+
// Repository gets the RepositoryClient for the specified RepositoryRef
50+
Repository(r RepositoryRef) RepositoryClient
51+
52+
// Repositories returns the RepositoriesClient handling sets of organizations
53+
Repositories() RepositoriesClient
54+
}
55+
56+
// OrganizationsClient operates on organizations the user has access to
57+
type OrganizationsClient interface {
58+
// Get a specific organization the user has access to
59+
// This might also refer to a sub-organization
60+
// ErrNotFound is returned if the resource does not exist
61+
Get(ctx context.Context, o OrganizationRef) (*Organization, error)
62+
63+
// List all top-level organizations the specific user has access to
64+
// List should return all available organizations, using multiple paginated requests if needed
65+
List(ctx context.Context) ([]Organization, error)
66+
67+
// Children returns the immediate child-organizations for the specific IdentityRef o.
68+
// The IdentityRef may point to any sub-organization that exists
69+
// This is not supported in GitHub
70+
// Children should return all available organizations, using multiple paginated requests if needed
71+
Children(ctx context.Context, o OrganizationRef) ([]Organization, error)
72+
73+
// Possibly add Create/Update/Delete methods later
74+
}
75+
76+
// OrganizationClient operates on a given/specific organization
77+
type OrganizationClient interface {
78+
// Teams gives access to the TeamsClient for this specific organization
79+
Teams() OrganizationTeamsClient
80+
}
81+
82+
// OrganizationTeamsClient handles teams organization-wide
83+
type OrganizationTeamsClient interface {
84+
// Get a team within the specific organization
85+
// teamName may include slashes, to point to e.g. "sub-teams" i.e. subgroups in Gitlab
86+
// teamName must not be an empty string
87+
// ErrNotFound is returned if the resource does not exist
88+
Get(ctx context.Context, teamName string) (*Team, error)
89+
90+
// List all teams (recursively, in terms of subgroups) within the specific organization
91+
// List should return all available organizations, using multiple paginated requests if needed
92+
List(ctx context.Context) ([]Team, error)
93+
94+
// Possibly add Create/Update/Delete methods later
95+
}
96+
97+
// RepositoriesClient operates on repositories the user has access to
98+
type RepositoriesClient interface {
99+
// Get returns the repository at the given path
100+
// ErrNotFound is returned if the resource does not exist
101+
Get(ctx context.Context, r RepositoryRef) (*Repository, error)
102+
103+
// List all repositories in the given organization or user account
104+
// List should return all available repositories, using multiple paginated requests if needed
105+
List(ctx context.Context, o IdentityRef) ([]Repository, error)
106+
107+
// Create creates a repository at the given organization path, with the given URL-encoded name and options
108+
// ErrAlreadyExists will be returned if the resource already exists
109+
Create(ctx context.Context, r *Repository, opts ...RepositoryCreateOption) (*Repository, error)
110+
111+
// Update will update the desired state of the repository. Only set fields will be respected.
112+
// ErrNotFound is returned if the resource does not exist
113+
Update(ctx context.Context, r *Repository) (*Repository, error)
114+
115+
// Reconcile makes sure r is the actual state in the backing Git provider. If r doesn't exist
116+
// under the hood, it is created. If r is already the actual state, this is a no-op. If r isn't
117+
// the actual state, the resource will be updated.
118+
Reconcile(ctx context.Context, r *Repository, opts ...RepositoryReconcileOption) (*Repository, error)
119+
}
120+
121+
// RepositoryClient operates on a given/specific repository
122+
type RepositoryClient interface {
123+
// TeamAccess returns a client for operating on the teams that have access to this specific repository
124+
TeamAccess() RepositoryTeamAccessClient
125+
126+
// Credentials gives access to manipulating credentials for accessing this specific repository
127+
Credentials() RepositoryCredentialsClient
128+
}
129+
130+
// RepositoryTeamAccessClient operates on the teams list for a specific repository
131+
type RepositoryTeamAccessClient interface {
132+
// Create adds a given team to the repo's team access control list
133+
// ErrAlreadyExists will be returned if the resource already exists
134+
// The embedded RepositoryInfo of ta does not need to be populated, but if it is,
135+
// it must equal to the RepositoryRef given to the RepositoryClient.
136+
Create(ctx context.Context, ta *TeamAccess) error
137+
138+
// Lists the team access control list for this repo
139+
List(ctx context.Context) ([]TeamAccess, error)
140+
141+
// Reconcile makes sure ta is the actual state in the backing Git provider. If ta doesn't exist
142+
// under the hood, it is created. If ta is already the actual state, this is a no-op. If ta isn't
143+
// the actual state, the resource will be deleted and recreated.
144+
// The embedded RepositoryInfo of ta does not need to be populated, but if it is,
145+
// it must equal to the RepositoryRef given to the RepositoryClient.
146+
Reconcile(ctx context.Context, ta *TeamAccess) (*TeamAccess, error)
147+
148+
// Delete removes the given team from the repo's team access control list
149+
// ErrNotFound is returned if the resource does not exist
150+
Delete(ctx context.Context, ta *TeamAccess) error
151+
}
152+
153+
// RepositoryCredentialsClient operates on the access credential list for a specific repository
154+
type RepositoryCredentialsClient interface {
155+
// Create a credential with the given human-readable name, the given bytes and optional options
156+
// ErrAlreadyExists will be returned if the resource already exists
157+
Create(ctx context.Context, c RepositoryCredential) (RepositoryCredential, error)
158+
159+
// Lists all credentials for the given credential type
160+
List(ctx context.Context, t RepositoryCredentialType) ([]RepositoryCredential, error)
161+
162+
// Reconcile makes sure c is the actual state in the backing Git provider. If c doesn't exist
163+
// under the hood, it is created. If c is already the actual state, this is a no-op. If c isn't
164+
// the actual state, the resource will deleted and recreated.
165+
Reconcile(ctx context.Context, c RepositoryCredential) (RepositoryCredential, error)
166+
167+
// Deletes a credential from the repo. name corresponds to GetName() of the credential
168+
// ErrNotFound is returned if the resource does not exist
169+
Delete(ctx context.Context, c RepositoryCredential) error
170+
}

enums.go

+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
Copyright 2020 The Flux CD contributors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package gitprovider
18+
19+
import "github.com/fluxcd/go-git-providers/validation"
20+
21+
// TransportType is an enum specifying the transport type used when cloning a repository
22+
type TransportType string
23+
24+
const (
25+
// TransportTypeHTTPS specifies a clone URL of the form:
26+
// https://<domain>/<org>/[<sub-orgs...>/]<repo>.git
27+
TransportTypeHTTPS = TransportType("https")
28+
// TransportTypeGit specifies a clone URL of the form:
29+
// git@<domain>:<org>/[<sub-orgs...>/]<repo>.git
30+
TransportTypeGit = TransportType("git")
31+
// TransportTypeSSH specifies a clone URL of the form:
32+
// ssh://git@<domain>/<org>/[<sub-orgs...>/]<repo>
33+
TransportTypeSSH = TransportType("ssh")
34+
)
35+
36+
// RepositoryCredentialType is an enum specifying the type of a certain repository credential
37+
type RepositoryCredentialType string
38+
39+
const (
40+
// RepositoryCredentialTypeDeployKey is the Deploy Key credential type
41+
// The struct used is DeployKey in this package
42+
RepositoryCredentialTypeDeployKey = RepositoryCredentialType("deploykey")
43+
)
44+
45+
// RepoVisibility is an enum specifying the visibility of a repository
46+
type RepoVisibility string
47+
48+
const (
49+
// RepoVisibilityPublic specifies that the repository should be publicly accessible
50+
RepoVisibilityPublic = RepoVisibility("public")
51+
// RepoVisibilityInternal specifies that the repository should accessible within the
52+
// own organization
53+
RepoVisibilityInternal = RepoVisibility("internal")
54+
// RepoVisibilityPrivate specifies that the repository should only be accessible by
55+
// specifically added team members
56+
RepoVisibilityPrivate = RepoVisibility("private")
57+
)
58+
59+
// knownRepoVisibilityValues is a map of known RepoVisibility values, used for validation
60+
var knownRepoVisibilityValues = map[RepoVisibility]struct{}{
61+
RepoVisibilityPublic: {},
62+
RepoVisibilityInternal: {},
63+
RepoVisibilityPrivate: {},
64+
}
65+
66+
// validateRepoVisibility validates a given RepoVisibility.
67+
// Use as errs.Append(validateRepoVisibility(visibility), visibility, "FieldName")
68+
func validateRepoVisibility(r RepoVisibility) error {
69+
_, ok := knownRepoVisibilityValues[r]
70+
if !ok {
71+
return validation.ErrFieldEnumInvalid
72+
}
73+
return nil
74+
}
75+
76+
// repoVisibilityVar returns a pointer to a RepoVisibility
77+
func repoVisibilityVar(r RepoVisibility) *RepoVisibility {
78+
return &r
79+
}
80+
81+
// RepositoryPermission is an enum specifying the access level for a certain team or person
82+
// for a given repository
83+
type RepositoryPermission string
84+
85+
const (
86+
// RepositoryPermissionPull ("pull") - team members can pull, but not push to or administer this repository
87+
// This is called "guest" in GitLab
88+
RepositoryPermissionPull = RepositoryPermission("pull")
89+
90+
// RepositoryPermissionTriage ("triage") - team members can proactively manage issues and pull requests without write access.
91+
// This is called "reporter" in GitLab
92+
RepositoryPermissionTriage = RepositoryPermission("triage")
93+
94+
// RepositoryPermissionPush ("push") - team members can pull and push, but not administer this repository
95+
// This is called "developer" in GitLab
96+
RepositoryPermissionPush = RepositoryPermission("push")
97+
98+
// RepositoryPermissionMaintain ("maintain") - team members can manage the repository without access to sensitive or destructive actions.
99+
// This is called "maintainer" in GitLab
100+
RepositoryPermissionMaintain = RepositoryPermission("maintain")
101+
102+
// RepositoryPermissionAdmin ("admin") - team members can pull, push and administer this repository
103+
// This is called "admin" or "owner" in GitLab
104+
RepositoryPermissionAdmin = RepositoryPermission("admin")
105+
)
106+
107+
// knownRepoVisibilityValues is a map of known RepositoryPermission values, used for validation
108+
var knownRepositoryPermissionValues = map[RepositoryPermission]struct{}{
109+
RepositoryPermissionPull: {},
110+
RepositoryPermissionTriage: {},
111+
RepositoryPermissionPush: {},
112+
RepositoryPermissionMaintain: {},
113+
RepositoryPermissionAdmin: {},
114+
}
115+
116+
// validateRepositoryPermission validates a given RepositoryPermission.
117+
// Use as errs.Append(validateRepositoryPermission(permission), permission, "FieldName")
118+
func validateRepositoryPermission(p RepositoryPermission) error {
119+
_, ok := knownRepositoryPermissionValues[p]
120+
if !ok {
121+
return validation.ErrFieldEnumInvalid
122+
}
123+
return nil
124+
}
125+
126+
// repositoryPermissionVar returns a pointer to a RepositoryPermission
127+
func repositoryPermissionVar(p RepositoryPermission) *RepositoryPermission {
128+
return &p
129+
}
130+
131+
// LicenseTemplate is an enum specifying a license template that can be used when creating a
132+
// repository. Examples of available licenses are here:
133+
// https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/licensing-a-repository#searching-github-by-license-type
134+
type LicenseTemplate string
135+
136+
const (
137+
// LicenseTemplateApache2 specifies use of the Apache 2.0 license, see
138+
// https://choosealicense.com/licenses/apache-2.0/
139+
LicenseTemplateApache2 = LicenseTemplate("apache-2.0")
140+
// LicenseTemplateMIT specifies use of the MIT license, see
141+
// https://choosealicense.com/licenses/mit/
142+
LicenseTemplateMIT = LicenseTemplate("mit")
143+
// LicenseTemplateGPL3 specifies use of the GNU General Public License v3.0, see
144+
// https://choosealicense.com/licenses/gpl-3.0/
145+
LicenseTemplateGPL3 = LicenseTemplate("gpl-3.0")
146+
)
147+
148+
// knownLicenseTemplateValues is a map of known LicenseTemplate values, used for validation
149+
var knownLicenseTemplateValues = map[LicenseTemplate]struct{}{
150+
LicenseTemplateApache2: {},
151+
LicenseTemplateMIT: {},
152+
LicenseTemplateGPL3: {},
153+
}
154+
155+
// validateLicenseTemplate validates a given LicenseTemplate.
156+
// Use as errs.Append(validateLicenseTemplate(template), template, "FieldName")
157+
func validateLicenseTemplate(t LicenseTemplate) error {
158+
_, ok := knownLicenseTemplateValues[t]
159+
if !ok {
160+
return validation.ErrFieldEnumInvalid
161+
}
162+
return nil
163+
}
164+
165+
// licenseTemplateVar returns a pointer to a LicenseTemplate
166+
func licenseTemplateVar(t LicenseTemplate) *LicenseTemplate {
167+
return &t
168+
}

0 commit comments

Comments
 (0)