Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync upstream main #144

Merged
merged 19 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
43deb74
fix(Earthfile): set the correct timestamps when building the go binaries
tampakrap Jun 12, 2024
1aa6a0a
feat(pkg-mgr): Support package installation with digests
ezgidemirel Sep 17, 2024
d0d4db1
Merge pull request #5965 from ezgidemirel/pkg-mgr-digest
turkenh Sep 19, 2024
114b865
Support installing Functions with v1 package metadata
negz Sep 19, 2024
f29a327
Use a mix of v1 and v1beta functions in E2E tests
negz Sep 19, 2024
6e99dd7
Merge pull request #5972 from negz/more-meta
negz Sep 20, 2024
8ccf771
resolves crossplane/crossplane#5975
cychiang Sep 21, 2024
fd21a2b
fix linting
cychiang Sep 21, 2024
40e92fe
- Rename function-secrets to function-credentials, for naming consistent
cychiang Sep 21, 2024
9bfd74c
handling function-credentials flag
cychiang Sep 22, 2024
084b017
fix linting
cychiang Sep 22, 2024
7a71444
fix(pkg-mgr): Update function linter to support metav1 and fix improp…
ezgidemirel Sep 20, 2024
ef0dd46
Merge pull request #5973 from ezgidemirel/fix-linter-and-digest
turkenh Sep 23, 2024
7a35a2a
- Remove `short` for `function-credentials`
cychiang Sep 23, 2024
843cc43
Merge pull request #5976 from cychiang/feat-5975-support-read-secrets…
phisco Sep 23, 2024
ea6242f
Merge pull request #5786 from tampakrap/earthfile_keep_ts
negz Sep 23, 2024
d8b3ce9
feat(Earthfile): Add checksums and tarballs for crank
tampakrap Jun 12, 2024
aee9bcb
Merge pull request #5779 from tampakrap/earthfile_checksums_tarballs
negz Sep 23, 2024
a11db05
Merge remote-tracking branch 'upstream/main' into sync-upstream-main
turkenh Sep 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
WITH DOCKER --load crossplane-e2e/crossplane:latest=(+image --CROSSPLANE_VERSION=v0.0.0-e2e)
# TODO(negz:) Set GITHUB_ACTIONS=true and use RUN --raw-output when
# https://github.com/earthly/earthly/issues/4143 is fixed.
RUN gotestsum --no-color=false --format testname --junitfile e2e-tests.xml --raw-command go tool test2json -t -p E2E ./e2e -test.v ${FLAGS}

Check failure on line 65 in Earthfile

View workflow job for this annotation

GitHub Actions / e2e-tests (ssa-claims)

Error

The command WITH DOCKER RUN --privileged gotestsum --no-color=false --format testname --junitfile e2e-tests.xml --raw-command go tool test2json -t -p E2E ./e2e -test.v ${FLAGS} did not complete successfully. Exit code 1
END
FINALLY
SAVE ARTIFACT --if-exists e2e-tests.xml AS LOCAL _output/tests/e2e-tests.xml
Expand Down Expand Up @@ -162,9 +162,17 @@
CACHE --id go-build --sharing shared /root/.cache/go-build
COPY --dir apis/ cmd/ internal/ pkg/ .
RUN go build -o crossplane${ext} ./cmd/crossplane
RUN sha256sum crossplane${ext} | head -c 64 > crossplane${ext}.sha256
RUN go build -o crank${ext} ./cmd/crank
SAVE ARTIFACT crossplane${ext} AS LOCAL _output/bin/${GOOS}_${GOARCH}/crossplane${ext}
SAVE ARTIFACT crank${ext} AS LOCAL _output/bin/${GOOS}_${GOARCH}/crank${ext}
RUN sha256sum crank${ext} | head -c 64 > crank${ext}.sha256
RUN tar -czvf crank.tar.gz crank${ext} crank${ext}.sha256
RUN sha256sum crank.tar.gz | head -c 64 > crank.tar.gz.sha256
SAVE ARTIFACT --keep-ts crossplane${ext} AS LOCAL _output/bin/${GOOS}_${GOARCH}/crossplane${ext}
SAVE ARTIFACT --keep-ts crossplane${ext}.sha256 AS LOCAL _output/bin/${GOOS}_${GOARCH}/crossplane${ext}.sha256
SAVE ARTIFACT --keep-ts crank${ext} AS LOCAL _output/bin/${GOOS}_${GOARCH}/crank${ext}
SAVE ARTIFACT --keep-ts crank${ext}.sha256 AS LOCAL _output/bin/${GOOS}_${GOARCH}/crank${ext}.sha256
SAVE ARTIFACT --keep-ts crank.tar.gz AS LOCAL _output/bundle/${GOOS}_${GOARCH}/crank.tar.gz
SAVE ARTIFACT --keep-ts crank.tar.gz.sha256 AS LOCAL _output/bundle/${GOOS}_${GOARCH}/crank.tar.gz.sha256

# go-multiplatform-build builds Crossplane binaries for all supported OS
# and architectures.
Expand Down
2 changes: 1 addition & 1 deletion apis/pkg/v1beta1/lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ type Dependency struct {
// Type is the type of package. Can be either Configuration or Provider.
Type PackageType `json:"type"`

// Constraints is a valid semver range, which will be used to select a valid
// Constraints is a valid semver range or a digest, which will be used to select a valid
// dependency version.
Constraints string `json:"constraints"`
}
Expand Down
2 changes: 1 addition & 1 deletion cluster/crds/pkg.crossplane.io_locks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ spec:
properties:
constraints:
description: |-
Constraints is a valid semver range, which will be used to select a valid
Constraints is a valid semver range or a digest, which will be used to select a valid
dependency version.
type: string
package:
Expand Down
31 changes: 23 additions & 8 deletions cmd/crank/render/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"github.com/alecthomas/kong"
"github.com/spf13/afero"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/serializer/json"

Expand All @@ -48,9 +49,10 @@ type Cmd struct {
ContextValues map[string]string `help:"Comma-separated context key-value pairs to pass to the Function pipeline. Values must be JSON. Keys take precedence over --context-files." mapsep:""`
IncludeFunctionResults bool `help:"Include informational and warning messages from Functions in the rendered output as resources of kind: Result." short:"r"`
IncludeFullXR bool `help:"Include a direct copy of the input XR's spec and metadata fields in the rendered output." short:"x"`
ObservedResources string `help:"A YAML file or directory of YAML files specifying the observed state of composed resources." placeholder:"PATH" short:"o" type:"path"`
ExtraResources string `help:"A YAML file or directory of YAML files specifying extra resources to pass to the Function pipeline." placeholder:"PATH" short:"e" type:"path"`
ObservedResources string `help:"A YAML file or directory of YAML files specifying the observed state of composed resources." placeholder:"PATH" short:"o" type:"path"`
ExtraResources string `help:"A YAML file or directory of YAML files specifying extra resources to pass to the Function pipeline." placeholder:"PATH" short:"e" type:"path"`
IncludeContext bool `help:"Include the context in the rendered output as a resource of kind: Context." short:"c"`
FunctionCredentials string `help:"A YAML file or directory of YAML files specifying credentials to use for Functions to render the XR." placeholder:"PATH" type:"path"`

Timeout time.Duration `default:"1m" help:"How long to run before timing out."`

Expand Down Expand Up @@ -109,6 +111,10 @@ Examples:
# Pass extra resources Functions in the pipeline can request.
crossplane render xr.yaml composition.yaml functions.yaml \
--extra-resources=extra-resources.yaml

# Pass credentials to Functions in the pipeline that need them.
crossplane render xr.yaml composition.yaml functions.yaml \
--function-credentials=credentials.yaml
`
}

Expand Down Expand Up @@ -149,6 +155,14 @@ func (c *Cmd) Run(k *kong.Context, log logging.Logger) error { //nolint:gocognit
return errors.Wrapf(err, "cannot load functions from %q", c.Functions)
}

fcreds := []corev1.Secret{}
if c.FunctionCredentials != "" {
fcreds, err = LoadCredentials(c.fs, c.FunctionCredentials)
if err != nil {
return errors.Wrapf(err, "cannot load secrets from %q", c.FunctionCredentials)
}
}

ors := []composed.Unstructured{}
if c.ObservedResources != "" {
ors, err = LoadObservedResources(c.fs, c.ObservedResources)
Expand Down Expand Up @@ -181,12 +195,13 @@ func (c *Cmd) Run(k *kong.Context, log logging.Logger) error { //nolint:gocognit
defer cancel()

out, err := Render(ctx, log, Inputs{
CompositeResource: xr,
Composition: comp,
Functions: fns,
ObservedResources: ors,
ExtraResources: ers,
Context: fctx,
CompositeResource: xr,
Composition: comp,
Functions: fns,
FunctionCredentials: fcreds,
ObservedResources: ors,
ExtraResources: ers,
Context: fctx,
})
if err != nil {
return errors.Wrap(err, "cannot render composite resource")
Expand Down
20 changes: 20 additions & 0 deletions cmd/crank/render/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"path/filepath"

"github.com/spf13/afero"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/yaml"

Expand Down Expand Up @@ -94,6 +95,25 @@ func LoadFunctions(filesys afero.Fs, file string) ([]pkgv1.Function, error) {
return functions, nil
}

// LoadCredentials from a stream of YAML manifests.
func LoadCredentials(fs afero.Fs, file string) ([]corev1.Secret, error) {
stream, err := LoadYAMLStream(fs, file)
if err != nil {
return nil, errors.Wrap(err, "cannot load YAML stream from file")
}

secrets := make([]corev1.Secret, 0, len(stream))
for _, y := range stream {
s := &corev1.Secret{}
if err := yaml.Unmarshal(y, s); err != nil {
return nil, errors.Wrap(err, "cannot parse YAML secret manifest")
}
secrets = append(secrets, *s)
}

return secrets, nil
}

// LoadExtraResources from a stream of YAML manifests.
func LoadExtraResources(fs afero.Fs, file string) ([]unstructured.Unstructured, error) {
stream, err := LoadYAMLStream(fs, file)
Expand Down
44 changes: 38 additions & 6 deletions cmd/crank/render/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/types/known/structpb"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
Expand Down Expand Up @@ -66,12 +67,13 @@ const (

// Inputs contains all inputs to the render process.
type Inputs struct {
CompositeResource *ucomposite.Unstructured
Composition *apiextensionsv1.Composition
Functions []pkgv1.Function
ObservedResources []composed.Unstructured
ExtraResources []unstructured.Unstructured
Context map[string][]byte
CompositeResource *ucomposite.Unstructured
Composition *apiextensionsv1.Composition
Functions []pkgv1.Function
FunctionCredentials []corev1.Secret
ObservedResources []composed.Unstructured
ExtraResources []unstructured.Unstructured
Context map[string][]byte

// TODO(negz): Allow supplying observed XR and composed resource connection
// details. Maybe as Secrets? What if secret stores are in use?
Expand Down Expand Up @@ -159,6 +161,16 @@ func (r *RuntimeFunctionRunner) Stop(ctx context.Context) error {
return nil
}

// getSecret retrieves the secret with the specified name and namespace from the provided list of secrets.
func getSecret(name string, nameSpace string, secrets []corev1.Secret) (*corev1.Secret, error) {
for _, s := range secrets {
if s.GetName() == name && s.GetNamespace() == nameSpace {
return &s, nil
}
}
return nil, errors.Errorf("secret %q not found", name)
}

// Render the desired XR and composed resources, sorted by resource name, given the supplied inputs.
func Render(ctx context.Context, log logging.Logger, in Inputs) (Outputs, error) { //nolint:gocognit // TODO(negz): Should we refactor to break this up a bit?
runtimes, err := NewRuntimeFunctionRunner(ctx, log, in.Functions)
Expand Down Expand Up @@ -227,6 +239,26 @@ func Render(ctx context.Context, log logging.Logger, in Inputs) (Outputs, error)
req.Input = in
}

req.Credentials = map[string]*fnv1.Credentials{}
for _, cs := range fn.Credentials {
// For now we only support loading credentials from secrets.
if cs.Source != apiextensionsv1.FunctionCredentialsSourceSecret || cs.SecretRef == nil {
continue
}

s, err := getSecret(cs.SecretRef.Name, cs.SecretRef.Namespace, in.FunctionCredentials)
if err != nil {
return Outputs{}, errors.Wrapf(err, "cannot get credentials from secret %q", cs.SecretRef.Name)
}
req.Credentials[cs.Name] = &fnv1.Credentials{
Source: &fnv1.Credentials_CredentialData{
CredentialData: &fnv1.CredentialData{
Data: s.Data,
},
},
}
}

rsp, err := runner.RunFunction(ctx, fn.FunctionRef.Name, req)
if err != nil {
return Outputs{}, errors.Wrapf(err, "cannot run pipeline step %q", fn.Step)
Expand Down
53 changes: 53 additions & 0 deletions cmd/crank/render/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/structpb"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -1046,6 +1047,58 @@ func TestFilterExtraResources(t *testing.T) {
}
}

func TestGetSecret(t *testing.T) {
secrets := []corev1.Secret{
{
ObjectMeta: metav1.ObjectMeta{
Name: "secret1",
Namespace: "namespace1",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "secret2",
Namespace: "namespace2",
},
},
}

tests := map[string]struct {
name string
namespace string
secrets []corev1.Secret
wantErr bool
}{
"SecretFound": {
name: "secret1",
namespace: "namespace1",
secrets: secrets,
wantErr: false,
},
"SecretNotFound": {
name: "secret3",
namespace: "namespace3",
secrets: secrets,
wantErr: true,
},
"SecretWrongNamespace": {
name: "secret1",
namespace: "namespace2",
secrets: secrets,
wantErr: true,
},
}

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
_, err := getSecret(tc.name, tc.namespace, tc.secrets)
if (err != nil) != tc.wantErr {
t.Errorf("getSecret() error = %v, wantErr %v", err, tc.wantErr)
}
})
}
}

func MustStructJSON(j string) *structpb.Struct {
s := &structpb.Struct{}
if err := protojson.Unmarshal([]byte(j), s); err != nil {
Expand Down
28 changes: 28 additions & 0 deletions internal/controller/pkg/manager/revisioner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"testing"

"github.com/google/go-cmp/cmp"
conregv1 "github.com/google/go-containerregistry/pkg/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

Expand Down Expand Up @@ -96,6 +97,33 @@ func TestPackageRevisioner(t *testing.T) {
digest: "return-me",
},
},
"SuccessfulDigest": {
reason: "Should return the digest of the package source image.",
args: args{
pkg: &v1.Provider{
ObjectMeta: metav1.ObjectMeta{
Name: "provider-nop",
},
Spec: v1.ProviderSpec{
PackageSpec: v1.PackageSpec{
Package: "crossplane-contrib/provider-nop@sha256:ecc25c121431dfc7058754427f97c034ecde26d4aafa0da16d258090e0443904",
PackagePullPolicy: &pullIfNotPresent,
},
},
},
f: &fake.MockFetcher{
MockHead: fake.NewMockHeadFn(&conregv1.Descriptor{
Digest: conregv1.Hash{
Algorithm: "sha256",
Hex: "ecc25c121431dfc7058754427f97c034ecde26d4aafa0da16d258090e0443904",
},
}, nil),
},
},
want: want{
digest: "provider-nop-ecc25c121431",
},
},
"ErrParseRef": {
reason: "Should return an error if we cannot parse reference from package source image.",
args: args{
Expand Down
Loading
Loading