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

BUILD-353: name changes, 2 CRDs instead of one for secrets and configmaps #55

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ deploy-no-refreshresources: deploy

crd:
# temporary creation of CRD until it lands in openshift/api, openshift/openshift-apiserver, etc.
oc apply -f ./deploy/0000_10_sharedresource.crd.yaml
oc apply -f ./deploy/0000_10_sharedsecret.crd.yaml
oc apply -f ./deploy/0000_10_sharedconfigmap.crd.yaml

test-e2e-no-deploy: crd
TEST_SUITE=$(TEST_SUITE) TEST_TIMEOUT=$(TEST_TIMEOUT) DAEMONSET_PODS=$(DAEMONSET_PODS) ./hack/test-e2e.sh
Expand Down
29 changes: 16 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,28 @@ Namespaces in Openshift.
The API used to achieve this support are:

- the `volume` and `volumeMount` fields of a Kubernetes Pod
- a new `SharedResource` Kubernetes Custom Resource Definition which specifies which Secret of ConfigMap is to be shared, and which
- a new `SharedConfigMap` Kubernetes Custom Resource Definition which specifies which ConfigMap is to be shared, and which
serves as the resource in Kubernetes Subject Access Review checks
- a new `SharedSecret` Kubernetes Custom Resource Definition which specifies which Secret is to be shared, and which
serves as the resource in Kubernetes Subject Access Review checks

## Features

- Supports only a subset of the Kubernetes CSIVolumeSource API. See [CSI Volume Specifics](docs/csi.md) for details.
- Initial pod requests for `SharedResource` CSI volumes are denied without both a valid `SharedResource` reference and
permissions to access that `SharedResource`.
- Changes to the `SharedResource`'s backing resource (kind, namespace, name) get reflected in data stored in the user pod's CSI volume.
- Subsequent removal of permissions for a `SharedResource` results in removal of the associated data stored in the user pod's CSI volume.
- Re-granting of permission for a `SharedResource` (after having the permissions initially, then removed) results in the associated
- Initial pod requests for `SharedConfigMap` or `SharedSecret` CSI volumes are denied without both a valid `SharedConfigMap` or `SharedSecret` reference and
permissions to access that `SharedConfigMap` or `SharedSecret`.
- Changes to the `SharedConfigMap` or `SharedSecret` backing resource (namespace, name) get reflected in data stored in the user pod's CSI volume.
- //TODO - do we now change the ability to change within a Pod between `SharedConfigMap` and `SharedSecret`
- Subsequent removal of permissions for a `SharedConfigMap` or `SharedSecret` results in removal of the associated data stored in the user pod's CSI volume.
- Re-granting of permission for a `SharedConfigMap` or `SharedSecret` (after having the permissions initially, then removed) results in the associated
data getting stored in the user pod's CSI volume.
- Removal of the `SharedResource` used to provision a `SharedResource` csi volume for a pod results in the associated data getting removed.
- Re-creation of a removed `SharedResource` for a previously provisioned `SharedResource` CSI volume results in the associated data
- Removal of the `SharedConfigMap` or `SharedSecret` used to provision a `SharedConfigMap` or `SharedSecret` csi volume for a pod results in the associated data getting removed.
- Re-creation of a removed `SharedConfigMap` or `SharedSecret` for a previously provisioned `SharedConfigMap` or `SharedSecret` CSI volume results in the associated data
reappearing in the user pod's CSI volume.
- Supports recycling of the csi driver so that previously provisioned CSI volumes are still managed; in other words,
the driver's internal state is persisted.
- Multiple `SharedResources` within a pod are allowed.
- When multiple `SharedResources` are mounted in a pod, one `SharedResource` can be mounted as a subdirectory of another `SharedResource`.
- When multiple `SharedResources` are mounted in a pod, one `SharedConfigMap` or `SharedSecret` can be mounted as a subdirectory of another `SharedConfigMap` or `SharedSecret`.


NOTE: see [CSI Volume Specifics](docs/csi.md) for restrictions around these features for read-only Volumes.
Expand All @@ -36,20 +39,20 @@ sufficient privileges to create namespaces and ServiceAccounts, and then create
and the creation of `CSIDrivers`.

Then, check out our [entry level example](docs/simple-example.md). You'll need to have sufficient privileges to create
namespaces, `Roles` and `RoleBindings`, instances of our new `SharedResource` CRD, and pods.
namespaces, `Roles` and `RoleBindings`, instances of our new `SharedConfigMap` or `SharedSecret` CRD, and pods.

The permission semantics in summary:
- the `ServiceAccount` associated with a `Pod` needs access to the 'use' verb on the `SharedResource` referenced any `CSIVolume`
- the `ServiceAccount` associated with a `Pod` needs access to the 'use' verb on the `SharedConfigMap` or `SharedSecret` referenced any `CSIVolume`
specified in a `Pod` that uses this repository's CSI Driver.
- separately, any `User` can discover cluster scoped `SharedResources` based on the permissions granted to them by their cluster
or namespace administrator.

The full definition of the `SharedResource` custom resource can be found [here](deploy/0000_10_sharedresource.crd.yaml).
The full definition of the `SharedConfigMap` can be found [here](deploy/0000_10_sharedconfigmap.crd.yaml) or `SharedSecret` custom resource can be found [here](deploy/0000_10_sharedsecret.crd.yaml).

For a more real world example of using this new driver to help with sharing RHEL entitlements, [this blog post](https://www.openshift.com/blog/the-path-to-improving-the-experience-with-rhel-entitlements-on-openshift)
dives into that scenario.

Next, for some details around support for updating `SharedResource` volumes as their corresponding Secrets and ConfigMaps change,
Next, for some details around support for updating `SharedConfigMap` or `SharedSecret` volumes as their corresponding Secrets or ConfigMaps change,
please visit [here](docs/content-update-details.md).

Lastly, for a depiction of details around the [features noted above](#features), check out this [FAQ](docs/faq.md).
5 changes: 3 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"

v1 "github.com/openshift/api/operator/v1"
"github.com/openshift/csi-driver-shared-resource/pkg/client"
"github.com/openshift/csi-driver-shared-resource/pkg/controller"
"github.com/openshift/csi-driver-shared-resource/pkg/hostpath"
Expand Down Expand Up @@ -79,7 +78,9 @@ func init() {

rootCmd.Flags().AddGoFlagSet(flag.CommandLine)
rootCmd.Flags().StringVar(&endPoint, "endpoint", "unix://tmp/csi.sock", "CSI endpoint")
rootCmd.Flags().StringVar(&driverName, "drivername", string(v1.SharedResourcesCSIDriver), "name of the driver")
//rootCmd.Flags().StringVar(&driverName, "drivername", string(v1.SharedResourcesCSIDriver), "name of the driver")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this commented out line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to leave it as per the TODO comment below we'll swtich back to it once you've updated that driver name with your openshift/api PR

//TODO short term bypassing openshift/api constant until it can be changed to the latest agreed upon name
rootCmd.Flags().StringVar(&driverName, "drivername", "csi.sharedresource.openshift.io", "name of the driver")
rootCmd.Flags().StringVar(&nodeID, "nodeid", "", "node id")
rootCmd.Flags().Int64Var(&maxVolumesPerNode, "maxvolumespernode", 0, "limit of volumes per node")
rootCmd.Flags().StringVar(&shareRelistInterval, "share-relist-interval", "",
Expand Down
104 changes: 104 additions & 0 deletions deploy/0000_10_sharedconfigmap.crd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# this is the boilerplate crd def that controller-gen reads and modifies with the
# contents from shared_configmap_type.go
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sharedconfigmaps.sharedresource.openshift.io
annotations:
displayName: SharedConfigMap
description: Extension for sharing ConfigMaps across Namespaces
spec:
scope: Cluster
group: sharedresource.openshift.io
names:
plural: sharedconfigmaps
singular: sharedconfigmap
kind: SharedConfigMap
listKind: SharedConfigMapList
versions:
- name: v1alpha1
served: true
storage: true
"schema":
"openAPIV3Schema":
description: "SharedConfigMap allows a ConfigMap to be shared across namespaces. Pods can mount the shared ConfigMap by adding a CSI volume to the pod specification using the \"csi.sharedresource.openshift.io\" CSI driver and a reference to the SharedConfigMap in the volume attributes: \n spec: volumes: - name: shared-configmap csi: driver: csi.sharedresource.openshift.io volumeAttributes: sharedConfigMap: my-share \n For the mount to be successful, the pod's service account must be granted permission to 'use' the named SharedConfigMap object within its namespace with an appropriate Role and RoleBinding. For compactness, here are example `oc` invocations for creating such Role and RoleBinding objects. \n `oc create role shared-resource-my-share --verb=use --resource=sharedconfigmaps.sharedresource.openshift.io --resource-name=my-share` `oc create rolebinding shared-resource-my-share --role=shared-resource-my-share --serviceaccount=my-namespace:default` \n Administrators can create separate Roles and RoleBindings for their users to be able the list and/or view the available cluster scoped SharedConfigMaps objects. \n Compatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support. These capabilities should not be used by applications needing long term support."
type: object
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Specification of the desired shared configmap
type: object
required:
- configmap
properties:
configmap:
description: configMap references the backing ConfigMap for this SharedConfigMap.
type: object
required:
- name
- namespace
properties:
name:
description: name represents the name of the ConfigMap or Secret that is being referenced.
type: string
namespace:
description: namespace represents the namespace where the referenced ConfigMap or Secret is located.
type: string
description:
description: description is a user readable explanation of what the backing resource provides.
type: string
status:
description: Observed status of the shared configmap
type: object
properties:
conditions:
description: conditions represents any observations made on this particular shared resource by the underlying CSI driver or Share controller.
type: array
items:
description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
type: object
required:
- lastTransitionTime
- message
- reason
- status
- type
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
type: string
format: date-time
message:
description: message is a human readable message indicating details about the transition. This may be an empty string.
type: string
maxLength: 32768
observedGeneration:
description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
type: integer
format: int64
minimum: 0
reason:
description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
type: string
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
status:
description: status of the condition, one of True, False, Unknown.
type: string
enum:
- "True"
- "False"
- Unknown
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
type: string
maxLength: 316
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])$