Skip to content

Commit feb2a9c

Browse files
committed
Initial working version of the source-controller integration
See examples/advanced/source for more information.
1 parent 2504419 commit feb2a9c

15 files changed

+1120
-22
lines changed

Makefile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ bin/goimports:
1313
rm -rf $$INSTALL_TMP_DIR ;\
1414
}
1515

16+
bin/source-controller:
17+
echo "Installing source-controller"
18+
@{ \
19+
set -e ;\
20+
INSTALL_TMP_DIR=$$(mktemp -d) ;\
21+
cd $$INSTALL_TMP_DIR ;\
22+
go mod init tmp ;\
23+
GOBIN=$(PWD)/bin go install github.com/fluxcd/source-controller ;\
24+
rm -rf $$INSTALL_TMP_DIR ;\
25+
}
26+
1627
bin/gofumpt:
1728
echo "Installing gofumpt"
1829
@{ \
@@ -35,6 +46,26 @@ bin/gci:
3546
rm -rf $$INSTALL_TMP_DIR ;\
3647
}
3748

49+
.PHONY: source-controller-crds
50+
source-controller-crds:
51+
# See https://stackoverflow.com/questions/600079/git-how-do-i-clone-a-subdirectory-only-of-a-git-repository/52269934#52269934
52+
echo "Fetching source-controller crds"
53+
@{ \
54+
set -xe ;\
55+
INSTALL_TMP_DIR=$$(mktemp -d) ;\
56+
cd $$INSTALL_TMP_DIR ;\
57+
git clone \
58+
--depth 1 \
59+
--filter=blob:none \
60+
--no-checkout \
61+
https://github.com/fluxcd/source-controller ;\
62+
cd source-controller ;\
63+
git checkout main -- config/crd/bases ;\
64+
rm -rf .git ;\
65+
cp config/crd/bases/* $(PWD)/examples/advanced/source/crds ;\
66+
rm -rf $$INSTALL_TMP_DIR ;\
67+
}
68+
3869
.PHONY: fmt
3970
fmt: bin/goimports bin/gci bin/gofumpt
4071
gofmt -w -s pkg .

examples/advanced/source/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Flux "Source Controller" Integration
2+
3+
`variant2` integrates with [source-controller](https://github.com/fluxcd/source-controller) to let the controller fetches "sources" like Git repositories, S3 buckets, and so on for your Variant command.
4+
5+
This integration allows you to run your Variant command in e.g. your CI pipeline while source-controller acts as a "cache" for the latest observed revision of your Git repository. This is much faster than your Variant command running `git clone` from scrach on each run, or much easier than implementing Git repository cache on your own.
6+
7+
To give it a try locally, you can follow the below steps:
8+
9+
- Run a `kind` cluster
10+
- Install source-controller CRDs with `kubectl apply -f crds/`
11+
- Install the sample `source` resource with `kubectl apply -f source/myrepo.yaml`
12+
- Run `variant run example`
13+
14+
`variant run example` fetches the latest observed revision of the Git repository configured in the `myrepo` "source" resource,
15+
by interacting with source-controller, and runs a series of commands on the fetched content.
16+
17+
## Notes
18+
19+
- See [the API reference](https://github.com/fluxcd/source-controller/blob/main/docs/api/source.md#source-api-reference) for more source "kinds" like Bucket, HelmChart, HelmRepository, etc.
20+
- Run `make source-controller-crds` to update the source-controller CRDs.
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
2+
---
3+
apiVersion: apiextensions.k8s.io/v1
4+
kind: CustomResourceDefinition
5+
metadata:
6+
annotations:
7+
controller-gen.kubebuilder.io/version: v0.3.0
8+
creationTimestamp: null
9+
name: buckets.source.toolkit.fluxcd.io
10+
spec:
11+
group: source.toolkit.fluxcd.io
12+
names:
13+
kind: Bucket
14+
listKind: BucketList
15+
plural: buckets
16+
singular: bucket
17+
scope: Namespaced
18+
versions:
19+
- additionalPrinterColumns:
20+
- jsonPath: .spec.url
21+
name: URL
22+
type: string
23+
- jsonPath: .status.conditions[?(@.type=="Ready")].status
24+
name: Ready
25+
type: string
26+
- jsonPath: .status.conditions[?(@.type=="Ready")].message
27+
name: Status
28+
type: string
29+
- jsonPath: .metadata.creationTimestamp
30+
name: Age
31+
type: date
32+
name: v1beta1
33+
schema:
34+
openAPIV3Schema:
35+
description: Bucket is the Schema for the buckets API
36+
properties:
37+
apiVersion:
38+
description: 'APIVersion defines the versioned schema of this representation
39+
of an object. Servers should convert recognized schemas to the latest
40+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
41+
type: string
42+
kind:
43+
description: 'Kind is a string value representing the REST resource this
44+
object represents. Servers may infer this from the endpoint the client
45+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
46+
type: string
47+
metadata:
48+
type: object
49+
spec:
50+
description: BucketSpec defines the desired state of an S3 compatible
51+
bucket
52+
properties:
53+
bucketName:
54+
description: The bucket name.
55+
type: string
56+
endpoint:
57+
description: The bucket endpoint address.
58+
type: string
59+
ignore:
60+
description: Ignore overrides the set of excluded patterns in the
61+
.sourceignore format (which is the same as .gitignore). If not provided,
62+
a default will be used, consult the documentation for your version
63+
to find out what those are.
64+
type: string
65+
insecure:
66+
description: Insecure allows connecting to a non-TLS S3 HTTP endpoint.
67+
type: boolean
68+
interval:
69+
description: The interval at which to check for bucket updates.
70+
type: string
71+
provider:
72+
default: generic
73+
description: The S3 compatible storage provider name, default ('generic').
74+
enum:
75+
- generic
76+
- aws
77+
type: string
78+
region:
79+
description: The bucket region.
80+
type: string
81+
secretRef:
82+
description: The name of the secret containing authentication credentials
83+
for the Bucket.
84+
properties:
85+
name:
86+
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
87+
TODO: Add other useful fields. apiVersion, kind, uid?'
88+
type: string
89+
type: object
90+
suspend:
91+
description: This flag tells the controller to suspend the reconciliation
92+
of this source.
93+
type: boolean
94+
timeout:
95+
default: 20s
96+
description: The timeout for download operations, defaults to 20s.
97+
type: string
98+
required:
99+
- bucketName
100+
- endpoint
101+
- interval
102+
type: object
103+
status:
104+
description: BucketStatus defines the observed state of a bucket
105+
properties:
106+
artifact:
107+
description: Artifact represents the output of the last successful
108+
Bucket sync.
109+
properties:
110+
checksum:
111+
description: Checksum is the SHA1 checksum of the artifact.
112+
type: string
113+
lastUpdateTime:
114+
description: LastUpdateTime is the timestamp corresponding to
115+
the last update of this artifact.
116+
format: date-time
117+
type: string
118+
path:
119+
description: Path is the relative file path of this artifact.
120+
type: string
121+
revision:
122+
description: Revision is a human readable identifier traceable
123+
in the origin source system. It can be a Git commit SHA, Git
124+
tag, a Helm index timestamp, a Helm chart version, etc.
125+
type: string
126+
url:
127+
description: URL is the HTTP address of this artifact.
128+
type: string
129+
required:
130+
- path
131+
- url
132+
type: object
133+
conditions:
134+
description: Conditions holds the conditions for the Bucket.
135+
items:
136+
description: "Condition contains details for one aspect of the current
137+
state of this API Resource. --- This struct is intended for direct
138+
use as an array at the field path .status.conditions. For example,
139+
type FooStatus struct{ // Represents the observations of a
140+
foo's current state. // Known .status.conditions.type are:
141+
\"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type
142+
\ // +patchStrategy=merge // +listType=map // +listMapKey=type
143+
\ Conditions []metav1.Condition `json:\"conditions,omitempty\"
144+
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`
145+
\n // other fields }"
146+
properties:
147+
lastTransitionTime:
148+
description: lastTransitionTime is the last time the condition
149+
transitioned from one status to another. This should be when
150+
the underlying condition changed. If that is not known, then
151+
using the time when the API field changed is acceptable.
152+
format: date-time
153+
type: string
154+
message:
155+
description: message is a human readable message indicating
156+
details about the transition. This may be an empty string.
157+
maxLength: 32768
158+
type: string
159+
observedGeneration:
160+
description: observedGeneration represents the .metadata.generation
161+
that the condition was set based upon. For instance, if .metadata.generation
162+
is currently 12, but the .status.conditions[x].observedGeneration
163+
is 9, the condition is out of date with respect to the current
164+
state of the instance.
165+
format: int64
166+
minimum: 0
167+
type: integer
168+
reason:
169+
description: reason contains a programmatic identifier indicating
170+
the reason for the condition's last transition. Producers
171+
of specific condition types may define expected values and
172+
meanings for this field, and whether the values are considered
173+
a guaranteed API. The value should be a CamelCase string.
174+
This field may not be empty.
175+
maxLength: 1024
176+
minLength: 1
177+
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
178+
type: string
179+
status:
180+
description: status of the condition, one of True, False, Unknown.
181+
enum:
182+
- "True"
183+
- "False"
184+
- Unknown
185+
type: string
186+
type:
187+
description: type of condition in CamelCase or in foo.example.com/CamelCase.
188+
--- Many .condition.type values are consistent across resources
189+
like Available, but because arbitrary conditions can be useful
190+
(see .node.status.conditions), the ability to deconflict is
191+
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
192+
maxLength: 316
193+
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
194+
type: string
195+
required:
196+
- lastTransitionTime
197+
- message
198+
- reason
199+
- status
200+
- type
201+
type: object
202+
type: array
203+
lastHandledReconcileAt:
204+
description: LastHandledReconcileAt holds the value of the most recent
205+
reconcile request value, so a change can be detected.
206+
type: string
207+
observedGeneration:
208+
description: ObservedGeneration is the last observed generation.
209+
format: int64
210+
type: integer
211+
url:
212+
description: URL is the download link for the artifact output of the
213+
last Bucket sync.
214+
type: string
215+
type: object
216+
type: object
217+
served: true
218+
storage: true
219+
subresources:
220+
status: {}
221+
status:
222+
acceptedNames:
223+
kind: ""
224+
plural: ""
225+
conditions: []
226+
storedVersions: []

0 commit comments

Comments
 (0)