Commit Graph

82 Commits

Author SHA1 Message Date
Michael Bridgen 18881d0231 Use events and metrics helpers
This commit replaces the explicit use of event recorder and metrics
with the helpers from github.com/fluxcd/pkg/runtime.

Doing so necessitated a few consts to represent the event "reasons",
so it is not a mechanical translation. Without thinking overly long
about it, I came up with a handful of reasons that I think will be
useful for filtering.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-11-30 17:50:16 +05:30
Michael Bridgen 8130273f7c Use patch.Helper to update the object
A pretty straight-forward change. NB the location of the `defer ...`
_after_ the exit if the object is suspended; this maintains the
invariant that the object will not be touched at all when suspended.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-11-30 16:33:31 +05:30
Michael Bridgen 99a1e39675 Port to conditions helpers
This commit rewrites the controller code so it uses the conditions
helpers from fluxcd/pkg/runtime/conditions.

It needs the fluxcd/source-controller/api module from the
reconcilers-dev branch, otherwise they will disagree on the methods in
fluxcd/pkg/apis/meta. Hence, variations on

    go get github.com/fluxcd/source-controller{,api}@reconcilers-dev

until I got both ./go.mod and ./api/go.mod to use modules from the
branch.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-11-30 16:29:40 +05:30
Stefan Prodan bfcb9ef8db
Remove deprecated io/ioutil
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-11-22 16:08:28 +02:00
Stefan Prodan 469988105d
Add the commit message to the event body
Drop "no updates made" event leave only the debug log in place.

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-11-09 12:26:52 +02:00
Aurel Canciu fe40819140
Fix unhandled error in signing key retrieval
Fixes #242

Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2021-11-04 22:12:10 +01:00
Sunny b299a9db59 Pass context to libgit2.RemoteCallbacks
Pass cancellable context to libgit2.RemoteCallbacks to be able to cancel
the remote operations when the context is cancelled.
For git clone, fetch and push, a context is created with the timeout of
the target GitRepository.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2021-11-04 18:36:13 +05:30
Hidde Beydals b29b87a7c5 controller: `Free` remaining `libgit2` objects
This supersedes #238.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-10-28 15:36:08 +02:00
Hidde Beydals c4b8b42164 controllers: use new `git` contract
This commit makes use of the refactored `git` package, which has
been reworked to increase stability and test coverage, and ensures
implementation details do not leak out into the "main wrapper".

This indirectly seems to resolve a memory leak that happenedd with
the previous wiring, thereby fixing #247.

The code changes for this controller itself are minimal, mostly
ensuring the auth and checkout configurations are created in the
"new way".

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-10-28 15:35:59 +02:00
Soule BA bc3d7b2112 Add support for the sprig functions library
All functions are not supported, The following are discarded:
            // Date functions
            "date",
            "date_in_zone",
            "date_modify",
            "now",
            "htmlDate",
            "htmlDateInZone",
            "dateInZone",
            "dateModify",

            // Strings
            "randAlphaNum",
            "randAlpha",
            "randAscii",
            "randNumeric",
            "uuidv4",

            // OS
            "env",
            "expandenv",

            // Network
            "getHostByName",

Signed-off-by: Soule BA <bah.soule@gmail.com>
2021-10-12 11:41:03 +02:00
Hidde Beydals 58e21f37fb Update github.com/libgit2/git2go to v31.6.1
This commit updates `github.com/libgit2/git2go` to `v31.6.1` (with
`libgit2` `1.1.1`), and changes the container image build process so
that it makes use of `ghcr.io/hiddeco/golang-with-libgit2`.

This image provides a pre-build dynamic `libgit2` dependency linked
against OpenSSL and LibSSH2 (without gcrypt), and a set of cross-compile
build tools (see
[rationale](https://github.com/hiddeco/golang-with-libgit2#rationale) and
[usage](https://github.com/hiddeco/golang-with-libgit2#usage) for more
detailed information).

The linked set of dependency should solve most known issues around
unsupport private key types, but does not resolve the issues with ECDSA*
and ED25519 hostkeys yet. Solving this requires a newer version of
`libgit2` (`>=1.2.0`), which currently does not seem to work properly
with `git2go/v32`.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-10-08 16:26:15 +02:00
Michael Bridgen b19eaf67f4 Use pkg/runtime consts for log levels
github.com/fluxcd/pkg/runtime/logger now supports the trace log level,
and has consts for the V(...) argument to supply. This commit updates
that module so to use those consts.

Previously, trace messages were output at the debug level; after this
commit they will be in their own level, so you need

    --log-level=trace

to see them.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-10-06 16:10:05 +01:00
David Korczynski 5a831a8a00
Fix nil-dereference in controller
Signed-off-by: David Korczynski <david@adalogics.com>
2021-09-29 18:06:11 +01:00
Michael Bridgen 3476ecb950 Fail push if a ref update is rejected
libgit2's Push method will succeed even when ref updates are rejected,
meaning it can silently fail if you e.g., use branch protection in
GitHub.

To make these errors visible, a callback is supplied to Push, which
checks for a non-empty status (on the advice of
https://libgit2.org/libgit2/#HEAD/group/callback/git_push_update_reference_cb).

For whatever reason, gogit seems overly sensitive to hook errors (in a
way that `git` and libgit2 aren't), and reports "invalid pkg-len
found" when it sees a rejected ref message. This doesn't affect the
runtime code, since that uses libgit2 -- but it does affect the test
code, which initialises the git repo used in many tests, so more care
is needed to push only the main branch, so as not to trigger a
rejection.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-07-13 16:06:17 +01:00
Michael Bridgen fd52463ac5 Use v1beta1 of the API from image reflector
This bumps the version of the image reflector types to v1beta1. This
doesn't technically make a difference for the minute, since the
Kubernetes API server would convert between versions, but is tidier.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-06-28 13:59:34 +01:00
Michael Bridgen 5b9631327f Graduate v1alpha2 API to v1beta1
This does the following:

 - copies the type definitions from v1alpha2 to v1beta1
 - changes the "stored" version to v1beta1
 - gives the CRD a conversion strategy of None, meaning just rewrite the version
 - switches the controller to use v1beta1
 - moves the generated documentation to v1beta1

This effectively rebadges the v1alpha2 version of this part of the
image API to v1beta1. The v1alpha2 version is left in place; there are
no conversion issues, as with v1alpha1->v1alpha2. The CRD specifies
that converting between v1alpha2 and v1beta1 just means changing the
version (i.e., the schema and semantics are the same).

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-06-28 11:26:59 +01:00
Max Jonas Werner 93782755ef
feat: add controller concurrency
The controller is now working with 4 concurrent workers by default.
This value is configurable through the `--concurrent` flag.

Signed-off-by: Max Jonas Werner <mail@makk.es>
2021-06-24 20:15:00 +02:00
Michael Bridgen 0a9c9a7437 Fill in tracking gaps
- trace different code paths, e.g., how the push branch is chosen
 - move debug output so it records things not already covered by e.g.,
   errors, events

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-06-23 12:23:36 +01:00
Michael Bridgen f011f2334e Thread debug/tracing through controller and pkg/
This commit finesses the use of the debug log a little, and introduces
a trace log. The trace log gets threaded through calls to utility
procedures -- it's a little awkward putting loggers into func
parameters and structs, but it always is.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-06-23 10:57:04 +01:00
Michael Bridgen 0b63def4fd Use libgit2 for clone, fetch, push
source-controller/pkg/git does shallow clones when using the go-git
implementation, and apparently this causes problems when fetching a
branch that has been merged at the origin:

    https://github.com/fluxcd/image-automation-controller/issues/164

So far as I can tell, getting a shallow clone breaks the automation,
no matter whether go-git or libgit2 is used for operations after
cloning. So: just use libgit2 for cloning, which means non-shallow
clones; and, for fetch and push, since there's no functional
difference between the implementations for those.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-06-02 15:00:36 +01:00
Hidde Beydals 3a1f6026b8 Switch to `github.com/ProtonMail/go-crypto/openpgp`
As `golang.org/x/crypto/openpgp` has been deprecated (see
https://github.com/golang/go/issues/44226 for details), and this is the
most active/used fork.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-05-26 14:47:27 +02:00
Stefan Prodan 9e7111be0f
Update source-controller/api to v0.12.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-04-22 10:59:47 +03:00
Stefan Prodan 833b50fdee
Move to ImagePolicy v1alpha2
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-04-22 10:03:22 +03:00
Michael Bridgen ebb2d6abea Use sourcev1.GitRepositoryRef
This changes the API so that the checkout field has a ref, the same as
GItRepository. This means you can check out a branch or a tag or a
particular commit. Most of these won't work unless you supply a branch
to push to as well.

An addtional change is that you can leave out the checkout altogether,
and the ref will default to that given in the GitRepository, or its
default. In the latter case, again you will need to provide a push
branch.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-04-13 11:01:42 +01:00
Michael Bridgen b28c5ccc04 Split author email and name into separate fields
This is a bit neater to read and write, and since I'm making breaking
changes anyway.

The name is now optional; an email is enough.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-04-13 10:50:01 +01:00
Michael Bridgen cd8a2e97b8 Flip the controller and tests to API v1alpha2
This finishes the v1alpha2 API, and rewrites everything needed so that
the controller supports it and the tests pass. For the most part, that
is just changing the location of fields. However, there's a few
notable extras:

 - check that the `sourceRef` is a git repo (that's the default), and
   that a `.spec.git` is supplied;

 - change a test that blindly patched an update object, so that it
   first gets the object it's patching. Previously, it succeeded
   because it was OK to patch everything to empty strings, but that's
   no longer the case since SourceReference.Kind is an enum.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-04-13 10:45:58 +01:00
Michael Bridgen cd895637b5 Ignore broken symlinks in commit
There is a bug in go-git which leads to it reporting broken, absolute
symlinks as modified whether they are or not:

    https://github.com/go-git/go-git/issues/253

To date, the controller checks whether the repo it has run an update
on is Clean, and as a consequence will run into the bug above if a
broken symlink is in the repo. The result is that it makes and pushes
an empty commit every interval.

To work around the problem, this commit adds a more careful check of
the repo status. Each file reported as modified is validated by
checking specifically that it's not a broken symlink: if `os.Lstat`
says it's a symlink and `os.Stat` reports the (target) file is
missing, it can be ignored. (Why not just ignore any missing file?
Because a missing file might indicate some other problem, so better to
let it fail).

For convenience, I have moved a few procedures around so they can be
used more readily by go tests.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-04-05 11:43:15 +01:00
Michael Bridgen 40fb66a217 Fetch remote branch before switching to it
For the "push to branch" feature, the controller must either switch to
the branch given, or create it starting at the checked-out HEAD. The
func `switchBranch` encapsulates this decision -- but it assumes that
if the branch exists at the remote, it will have been fetched when
cloning, and this is not always true. In particular, cloning with
go-git avoids fetching all refs:

    https://github.com/fluxcd/source-controller/blob/v0.11.0/pkg/git/gogit/checkout.go

This commit adds a step to fetch the remote branch to a local branch,
before attempting to switch to the local branch. This makes
`switchBranch` a little simpler, and doesn't rely on any refs having
been fetched ahead of time.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-04-03 15:11:20 +01:00
Michael Bridgen ddd0a8d8ed Watch ImagePolicy objects
Prior to #27, controller indexed the automation objects against image
policies, since an automation could depend on a specific image
policy. That PR removed the references and the watch; however,
automation objects still depend on image policy objects, just
indirectly through the git repo.

This commit reinstates the watch, and makes sure the generation change
/ reconcile request predicate applies only to the watch on automation
object themselves.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-04-02 20:12:13 +01:00
LWJ d1cfabf793 Fix nil pointer dereference and minor refactor
Signed-off-by: LWJ <lwjames1996@gmail.com>
2021-03-29 18:16:37 +01:00
LWJ b668e99a91 SigningKey modifications to align process with SOPS
Signed-off-by: LWJ <lwjames1996@gmail.com>
2021-03-24 21:54:31 +00:00
LWJ 4aa56f1013 Add SigningKey to CommitSpec
Signed-off-by: LWJ <lwjames1996@gmail.com>
2021-03-24 21:54:31 +00:00
Kevin McDermott 09616174f3 Update ImageUpdateAutomation Status with Patch.
This changes the functionality when updating the status to use Patch
rather than Updating, which is more resilient to changes.

Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
2021-03-22 09:45:00 +00:00
Somtochi Onyekwere ace1fbc263 Record suspension metrics
Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
2021-03-17 17:51:33 +01:00
Stefan Prodan 2e53745a03
Allow specifying the path for manifests updates
- Add optional `path` field to `spec.update`, defaults to the git repo root
- Restrict updates to the specified `spec.update.path`

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-03-16 11:58:21 +02:00
Michael Bridgen f90846b247 Implement .spec.push.branch most simply
This adapts the controller so that it will honour the
`.spec.push.branch` field.

The behaviour _without_ that field is to check out the branch given in
`.spec.checkout.branch`, commit, and push to the origin.

With `.spec.push.branch` present, it will try to check out that
branch; if it doesn't exist, it'll create it, starting from
`.spec.checkout.branch`. Either way it'll commit to that branch and
push to the origin.

The effect is that all automation will happen on the "push" branch,
and (most likely) not be applied into the cluster until merged into
whichever branch is synced. When the push branch is deleted, it'll be
created anew; otherwise, commits will pile up there as more changes
are made.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-03-05 15:17:28 +00:00
Michael Bridgen df7d570ae5 Give details of template data in spec docs
This explains the data available to the commit message template in the
API guide. While writing it, I realised it could be made more
convenient, so:

 - mask external types by embedding them
 - make the most useful parts of an image ref available using a
   wrapper struct and interface

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-03-03 11:08:53 +00:00
Michael Bridgen 908f8b775c Supply values to the commit message template
This commit:

 - passes a value including the update result to the commit message
   template
 - gives the template result a method for enumerating the
   objects regardless of file

This means you can access the images updated either by file
(`.Files`), by object (`.Objects()`), or just as a list
(`.Images()`). The additional test case shows how to use these.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-03-01 22:25:25 +00:00
Michael Bridgen fbdfa78e87 Adapt pkg/update so it returns a report of updates
It's desirable (see #6) to be able to enumerate the updates that were
made by automation, in the commit message and perhaps in an event
announcing success.

Doing this is counter-intuitively difficult. A `kyaml.setters2.Set`
filter will keep a count of the times its used. Previously, one `Set`
was used with the `SetAll` flag set, which would replace any marker
that corresponded to an image, in one traversal. But to keep track of
images individually, you need to have a setter for _each_ image (and
its tag, and its name, since those can be used separately). This means
`3 x policies` traversals of each node! The saving grace, possibly, is
that only files with a marker in them are considered.

Since you might want to dice the results in different ways, the result
returned is a nested map of file->object->image.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-03-01 17:38:31 +00:00
Michael Bridgen 12a339a0e6 Reformat git push errors from libgit2, go-git
libgit2 and go-git both have flaws in the way they treat errors from
the remote. go-git takes only the first line, meaning that it gets a
blank error message from GitLab which like to respond with a
banner. libgit2 returns the whole response, including blank lines and
fences ("=========...").

This commit corrects for both these flaws, by supplying a message if
go-git has taken a blank line, and stripping out blank lines and
fences from libgit2's error. This is unavoidably a brittle approach,
so I have limited it to just the situation that was reported as a
problem: pushing to the upstream git repo.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-25 11:17:36 +00:00
Michael Bridgen 172dec486c Test SSH as well as HTTP access to git
This commit rearranges update tests so that those that check that
updates are made can be run against a git server using SSH as well as
HTTP.

The local clone, used to provoke automated updates and to check
results, still uses HTTP. Those operations are not under test.

libgit2 wants to be asked for authentication when using SSH, and will
balk if it's not requested by the server. To avoid that, auth must be
switched on for the git test server.

This also switches auth on for HTTP, so it's necessary to use a git
URL that includes credentials for setting things up with a local
clone. I have also used that URL for the git-over-HTTP tests -- it's
arguable whether it's necessary to test that works, here.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-11 13:44:20 +00:00
Michael Bridgen 5d9f0f9958 Replace hard-wired GitImpl'n to that from spec
The "auth strategy", which depends on the GitImplementation, was
hard-wired to the "gogit" constant, but it should come from the
GitRepository spec. When the implementation is "libgit2" and the git
URL entails SSH, the result would normally include a callback for
checking the host key against known_hosts; but since it was
hard-wired, it was missing that callback.

This explains at least some instances of the error `user cancelled
hostkey check` from #106. The error, or a close relative, might also
arise if the callback rejects the host key because the host as it
appears in the known_hosts doesn't match that host as passed to the
callback -- see
https://github.com/fluxcd/source-controller/issues/287.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-11 13:44:20 +00:00
Michael Bridgen bd76267be5 Reform update strategy types
It's convenient to be able to leave out the update strategy, since
there is only one possible value at present; and if there were
alternatives, the present choice would still be a reasonable
default. However, with the format as it is, this doesn't work with
OpenAPIv3 schema, so you have to supply a value, even though there are
no parameters:

```yaml
spec:
  update:
    setters: {}
```

A more self-explanatory format which _does_ work with defaulting is to
name the strategy rather than relying on the presence of a field:

```yaml
spec:
  update:
    strategy: Setters
```

The whole `update` field can be elided and left to default. This
doesn't preclude having other strategies later, even those with
parameters, e.g.,

```yaml
spec:
  update:
    strategy: Foo
    fooParam: 5
```

This commit changes the API types and code that uses them, and the CRD
manifest, and adds a test that checks the defaulting actually works.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-01-20 13:16:18 +00:00
Michael Bridgen 4fde199362 Make both clone and push depend on the git impl
This follows up the stage-setting in prior commits, by respecting the
GitImplementation field given in the GitRepository object. NB it only
matters for cloning and pushing, so gogit is used in the "middle" to
record the commit in the local checkout.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-01-14 14:19:22 +01:00
Michael Bridgen 6866f98306 Separate commit and push
This separates the commit and push steps, since the commit step just
uses gogit, while the push step will dispatch based on the git
implementation.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-01-14 14:19:22 +01:00
Michael Bridgen 5e0ee72e68 Make sure clone and push work with libgit2
This commit changes the clone and push code to use libgit2. In the
case of clone, this means simply passing the const representing the
libgit2 implementation to the source-controller/pkg/git function. In
the case of push, this means adding a small helper to do the required
invocation.

NB:

 - there's no need to use libgit2 for operations other than clone and
   push; in particular, commits can have a single, go-git
   implementation.

 - libgit2's push is quite sensitive to the refspec it's given;
   `<branch>:refs/heads/<branch>` didn't work, and supplying no
   refspecs makes it time out.

 - libgit2 push will only work with a repository on disk that was
   cloned by libgit2 -- it's initialising the repo differently to
   go-git. This is surprising (a git repo is a git repo, isn't it?),
   but fine -- any given automation will use _either_ go-git or
   libgit2 for both of clone and push.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-01-14 14:17:02 +01:00
Michael Bridgen 861320075a Update to source-controller 0.5.2
This updates the source controller module to v0.5.2, and adjusts the
use of the git package therein. The main change there is that it now
accounts for two different git implementations -- go-git and libgit2
-- but I have not exposed that difference, just made it work as it did
before.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-01-14 14:15:55 +01:00
Hidde Beydals 0531deaaed Upgrade controller-runtime to v0.7.0
This commit upgrades the `controller-runtime` dependency to `v0.7.0`,
including all changes required to make all wiring work again.

- Upgrade `runtime` to v0.6.2 to include `controller-runtime` changes.
- Logger has been removed from the reconciler, and is now retrieved
  from the `context.Context` passed to the `Reconcile` method and
  downwards functions.
- Logger configuration flags are now bound to the flag set using
  `BindFlags` from `runtime/logger`, ensuring the same contract across
  GitOps Toolkit controllers, and the `--log-json` flag has been
  deprecated in favour of the `--log-encoding=json` default.
- The `ChangePredicate` from `runtime` has changed to a
  `ReconcileRequestedPredicate`, and is now chained with the
  `GenerationChangedPredicate` from `controller-runtime` using
  `predicate.Or`.
- Signatures that made use of `runtime.Object` have changed to
  `client.Object`, removing the requirement to e.g. call
  `runtime.Object#Object`.
- The `leader-election-role` was changed, as leader election now works
  via the `coordination/v1` API.

Other notable changes:

- Upgrade of `image-reflector-controller` API package to include
  controller-runtime changes.
- Upgrade of `source-controller` API package to v0.6.1.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-01-14 13:48:37 +01:00
Michael Bridgen 50a4e91344 Use short hash in condition message
Signed-off-by: Michael Bridgen <michael@weave.works>
2021-01-05 17:28:35 +00:00
Michael Bridgen eb7ca1f3bd Record the last pushed SHA1 and the time it was pushed
This adds fields to the ImageUpdateAutomation status for recording the
commit last pushed; handy to see when you are expecting a change.

It also adapts the "steady state" message of the ready condition to
mention the last commit, in case that's where people are looking.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-01-05 17:01:13 +00:00