diff --git a/api/v1alpha1/bundle_types.go b/api/v1alpha1/bundle_types.go index 741de32f..d09db9ab 100644 --- a/api/v1alpha1/bundle_types.go +++ b/api/v1alpha1/bundle_types.go @@ -100,8 +100,6 @@ type GitSource struct { Auth Authorization `json:"auth,omitempty"` } -// +kubebuilder:storageversion - type ConfigMapSource struct { // ConfigMap is a reference to a configmap in the rukpak system namespace ConfigMap corev1.LocalObjectReference `json:"configMap"` @@ -164,7 +162,6 @@ type BundleStatus struct { //+kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp` //+kubebuilder:printcolumn:name=Provisioner,type=string,JSONPath=`.spec.provisionerClassName`,priority=1 //+kubebuilder:printcolumn:name=Resolved Source,type=string,JSONPath=`.status.resolvedSource`,priority=1 -// +kubebuilder:storageversion // Bundle is the Schema for the bundles API type Bundle struct { diff --git a/api/v1alpha2/bundledeployment_types.go b/api/v1alpha2/bundledeployment_types.go index f18e6c3c..1fc09f91 100644 --- a/api/v1alpha2/bundledeployment_types.go +++ b/api/v1alpha2/bundledeployment_types.go @@ -44,7 +44,6 @@ const ( // +kubebuilder:object:root=true // +kubebuilder:subresource:status // +kubebuilder:resource:scope=Cluster,shortName={"bd","bds"} -// +kubebuilder:storageversion // +kubebuilder:printcolumn:name="Install State",type=string,JSONPath=`.status.conditions[?(.type=="Installed")].reason` // +kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp` @@ -102,7 +101,6 @@ const ( type BundleDeploymentStatus struct { Conditions []metav1.Condition `json:"conditions,omitempty"` ObservedGeneration int64 `json:"observedGeneration,omitempty"` - CachedBundles []string `json:"cachedbundles,omitempty"` } // BundleDeploymentList contains a list of BundleDeployment diff --git a/api/v1alpha2/zz_generated.deepcopy.go b/api/v1alpha2/zz_generated.deepcopy.go index 37f5ff16..762e1bd3 100644 --- a/api/v1alpha2/zz_generated.deepcopy.go +++ b/api/v1alpha2/zz_generated.deepcopy.go @@ -48,7 +48,7 @@ func (in *BundleDeplopymentSource) DeepCopyInto(out *BundleDeplopymentSource) { if in.Image != nil { in, out := &in.Image, &out.Image *out = new(ImageSource) - **out = **in + (*in).DeepCopyInto(*out) } if in.Git != nil { in, out := &in.Git, &out.Git @@ -164,11 +164,6 @@ func (in *BundleDeploymentStatus) DeepCopyInto(out *BundleDeploymentStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.CachedBundles != nil { - in, out := &in.CachedBundles, &out.CachedBundles - *out = make([]string, len(*in)) - copy(*out, *in) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BundleDeploymentStatus. @@ -232,6 +227,11 @@ func (in *HTTPSource) DeepCopy() *HTTPSource { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageSource) DeepCopyInto(out *ImageSource) { *out = *in + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(Authorization) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageSource. diff --git a/internal/controllers/v1alpha2/controllers/bundledeployment/bundledeployment.go b/internal/controllers/v1alpha2/controllers/bundledeployment/bundledeployment.go index ede52b14..07789262 100644 --- a/internal/controllers/v1alpha2/controllers/bundledeployment/bundledeployment.go +++ b/internal/controllers/v1alpha2/controllers/bundledeployment/bundledeployment.go @@ -144,15 +144,16 @@ func (b *bundleDeploymentReconciler) reconcile(ctx context.Context, bd *v1alpha2 bundleDepFS, res, err := b.unpackContents(ctx, bd) switch res.State { case v1alpha2source.StateUnpackPending: - setUnpackStatusPending(&bd.Status.Conditions, fmt.Sprintf("pending unpack pod"), bd.Generation) + // Explicitely state that error is nil during phases when unpacking is preogressing. + setUnpackStatusPending(&bd.Status.Conditions, fmt.Sprintf("pending unpack pod: err %v", err), bd.Generation) // Requeing after 5 sec for now since the average time to unpack an registry bundle locally - // was around ~4sec. - return ctrl.Result{RequeueAfter: 5 * time.Second}, nil + // was around ~4sec. Also requeing the err, in case it exists. + return ctrl.Result{RequeueAfter: 5 * time.Second}, err case v1alpha2source.StateUnpacking: - setUnpackStatusPending(&bd.Status.Conditions, fmt.Sprintf("unpacking pod"), bd.Generation) - return ctrl.Result{RequeueAfter: 5 * time.Second}, nil + setUnpackStatusPending(&bd.Status.Conditions, fmt.Sprintf("unpacking pod: err %v", err), bd.Generation) + return ctrl.Result{RequeueAfter: 5 * time.Second}, err case v1alpha2source.StateUnpackFailed: - setUnpackStatusFailing(&bd.Status.Conditions, err.Error(), bd.Generation) + setUnpackStatusFailing(&bd.Status.Conditions, fmt.Sprintf("unpacking failed: err %v", err), bd.Generation) return ctrl.Result{}, err case v1alpha2source.StateUnpacked: setUnpackStatusSuccess(&bd.Status.Conditions, fmt.Sprintf("unpacked %s", bd.GetName()), bd.Generation) @@ -245,14 +246,15 @@ func (b *bundleDeploymentReconciler) unpackContents(ctx context.Context, bd *v1a } // Even if one source has not unpacked, update Bundle Deployment status accordingly. + // In this case the status will contain the result from the first source + // which is still waiting to be unpacked. for _, res := range unpackResult { - if res.State == v1alpha2source.StateUnpackFailed { - return &bundleDepFs, res, apimacherrors.NewAggregate(errs) - } if res.State != v1alpha2source.StateUnpacked { - return &bundleDepFs, res, nil + return &bundleDepFs, res, apimacherrors.NewAggregate(errs) } } + + // TODO: capture the list of resolved sources for all the successful entry points. return &bundleDepFs, v1alpha2source.Result{State: v1alpha2source.StateUnpacked, Message: "Successfully unpacked"}, nil } diff --git a/internal/controllers/v1alpha2/source/git.go b/internal/controllers/v1alpha2/source/git.go index baf51952..5a514b19 100644 --- a/internal/controllers/v1alpha2/source/git.go +++ b/internal/controllers/v1alpha2/source/git.go @@ -124,7 +124,7 @@ func (r *Git) Unpack(ctx context.Context, bundeDepName string, bundleSrc v1alpha } resolvedSource := &v1alpha2.BundleDeplopymentSource{ - Kind: v1alpha2.SourceTypeGit, + Kind: v1alpha2.SourceKindGit, Git: resolvedGit, } return &Result{ResolvedSource: resolvedSource, State: StateUnpacked, Message: "Successfully unpacked git bundle"}, nil @@ -140,7 +140,7 @@ func deleteCacheDir(fs afero.Fs) error { } func (r *Git) validate(bundleSrc v1alpha2.BundleDeplopymentSource) error { - if bundleSrc.Kind != v1alpha2.SourceTypeGit { + if bundleSrc.Kind != v1alpha2.SourceKindGit { return fmt.Errorf("bundle source type %q not supported", bundleSrc.Kind) } if bundleSrc.Git == nil { diff --git a/internal/controllers/v1alpha2/source/image.go b/internal/controllers/v1alpha2/source/image.go index 11bdf446..d1cd19ac 100644 --- a/internal/controllers/v1alpha2/source/image.go +++ b/internal/controllers/v1alpha2/source/image.go @@ -69,7 +69,7 @@ func (i *Image) unpack(ctx context.Context, bdName, storagePath string, bdSrc v1 } func (i *Image) validate(bdSrc *v1alpha2.BundleDeplopymentSource, opts UnpackOption) error { - if bdSrc.Kind != v1alpha2.SourceTypeImage { + if bdSrc.Kind != v1alpha2.SourceKindImage { return fmt.Errorf("bundle source type %q not supported", bdSrc.Kind) } if bdSrc.Image == nil { @@ -147,8 +147,8 @@ func (i *Image) succeededPodResult(ctx context.Context, pod *corev1.Pod, storage } resolvedSource := &v1alpha2.BundleDeplopymentSource{ - Kind: v1alpha2.SourceTypeImage, - Image: &v1alpha2.ImageSource{ImageRef: digest}, + Kind: v1alpha2.SourceKindImage, + Image: &v1alpha2.ImageSource{Ref: digest}, } return &Result{ResolvedSource: resolvedSource, State: StateUnpacked}, nil @@ -211,7 +211,7 @@ func (i *Image) getDesiredPodApplyConfig(bdName string, bundleSrc *v1alpha2.Bund ). WithContainers(applyconfigurationcorev1.Container(). WithName(imageBundleUnpackContainerName). - WithImage(bundleSrc.Image.ImageRef). + WithImage(bundleSrc.Image.Ref). WithCommand("/bin/unpack", "--bundle-dir", "/"). WithVolumeMounts(applyconfigurationcorev1.VolumeMount(). WithName("util"). @@ -231,9 +231,9 @@ func (i *Image) getDesiredPodApplyConfig(bdName string, bundleSrc *v1alpha2.Bund ), ) - if bundleSrc.Image.ImagePullSecretName != "" { + if bundleSrc.Image.Auth != nil && bundleSrc.Image.Auth.Secret.Name != "" { podApply.Spec = podApply.Spec.WithImagePullSecrets( - applyconfigurationcorev1.LocalObjectReference().WithName(bundleSrc.Image.ImagePullSecretName), + applyconfigurationcorev1.LocalObjectReference().WithName(bundleSrc.Image.Auth.Secret.Name), ) } return podApply diff --git a/internal/controllers/v1alpha2/source/unpacker.go b/internal/controllers/v1alpha2/source/unpacker.go index 2f9ff28f..5b426763 100644 --- a/internal/controllers/v1alpha2/source/unpacker.go +++ b/internal/controllers/v1alpha2/source/unpacker.go @@ -73,7 +73,7 @@ type defaultUnpacker struct { unpackImage string baseUploadManagerURL string rootCAs *x509.CertPool - sources map[v1alpha2.SourceType]Unpacker + sources map[v1alpha2.SourceKind]Unpacker } type UnpackerOption func(*defaultUnpacker) @@ -97,13 +97,13 @@ func WithRootCAs(rootCAs *x509.CertPool) UnpackerOption { } type unpacker struct { - sources map[v1alpha2.SourceType]Unpacker + sources map[v1alpha2.SourceKind]Unpacker bd *v1alpha2.BundleDeplopymentSource } // NewUnpacker returns a new composite Source that unpacks bundles using the source // mapping provided by the configured sources. -func NewUnpacker(sources map[v1alpha2.SourceType]Unpacker) Unpacker { +func NewUnpacker(sources map[v1alpha2.SourceKind]Unpacker) Unpacker { return &unpacker{sources: sources} } @@ -148,12 +148,12 @@ func (u *defaultUnpacker) initialize() (Unpacker, error) { } httpTransport.TLSClientConfig.RootCAs = u.rootCAs - return NewUnpacker(map[v1alpha2.SourceType]Unpacker{ - v1alpha2.SourceTypeGit: &Git{ + return NewUnpacker(map[v1alpha2.SourceKind]Unpacker{ + v1alpha2.SourceKindGit: &Git{ Reader: u.systemNsCluster.GetClient(), SecretNamespace: u.namespace, }, - v1alpha2.SourceTypeImage: &Image{ + v1alpha2.SourceKindImage: &Image{ Client: u.systemNsCluster.GetClient(), KubeClient: kubeclient, PodNamespace: u.namespace, diff --git a/manifests/base/apis/crds/core.rukpak.io_bundledeployments.yaml b/manifests/base/apis/crds/core.rukpak.io_bundledeployments.yaml index e2a5307b..f39e7c03 100644 --- a/manifests/base/apis/crds/core.rukpak.io_bundledeployments.yaml +++ b/manifests/base/apis/crds/core.rukpak.io_bundledeployments.yaml @@ -386,10 +386,6 @@ spec: spec: description: BundleDeploymentSpec defines the desired state of BundleDeployment properties: -<<<<<<< HEAD - defaultnamespace: - type: string -======= config: description: 'Config is provisioner specific configurations TODO: This should be become deployer specific. Should move to helm deployer @@ -408,11 +404,8 @@ spec: type: string paused: default: false - description: Paused is used to configure whether we want the bundle - deployment to reconcile, or remmain in the last observed state. type: boolean sources: - description: Source configures how to pull the bundle content. items: properties: destination: @@ -457,7 +450,8 @@ spec: x-kubernetes-map-type: atomic type: object directory: - default: manifests + description: Directory refers to the location of the bundle + within the git repository. type: string ref: description: Ref configures the git source to clone a specific @@ -539,20 +533,48 @@ spec: description: Image is the bundle image that backs the content of this bundle. properties: - imageref: + auth: + description: Auth configures the authentication method if + necessary. + properties: + insecureSkipVerify: + description: InsecureSkipVerify controls whether a client + verifies the server's certificate chain and host name. + If InsecureSkipVerify is true, the clone operation + will accept any certificate presented by the server + and any host name in that certificate. In this mode, + TLS is susceptible to machine-in-the-middle attacks + unless custom verification is used. This should be + used only for testing. + type: boolean + secret: + description: Secret contains reference to the secret + that has authorization information and is in the namespace + that the provisioner is deployed. The secret is expected + to contain `data.username` and `data.password` for + the username and password, respectively for http(s) + scheme. Refer to https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret + For the ssh authorization of the GitSource, the secret + is expected to contain `data.ssh-privatekey` and `data.ssh-knownhosts` + for the ssh privatekey and the host entry in the known_hosts + file respectively. Refer to https://kubernetes.io/docs/concepts/configuration/secret/#ssh-authentication-secrets + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + x-kubernetes-map-type: atomic + type: object + ref: description: Ref contains the reference to a container image containing Bundle contents. type: string - pullSecret: - description: ImagePullSecretName contains the name of the - image pull secret in the namespace that the provisioner - is deployed. - type: string required: - - imageref + - ref type: object kind: - description: Kind of source being passed type: string required: - kind