Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/v1alpha1/cdapmaster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ type CDAPServiceSpec struct {
AdditionalVolumeMounts []corev1.VolumeMount `json:"additionalVolumeMounts,omitempty"`
// SecurityContext overrides the security context for the service pods.
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
// Lifecycle is to specify Container Lifecycle hooks provided by Kubernetes for containers.
// This will not be applied to the init containers as init containers do not support lifecycle.
Lifecycle *corev1.Lifecycle `json:"lifecycle,omitempty"`
}

// CDAPScalableServiceSpec defines the base specification for master services that can have more than one instance.
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2,090 changes: 2,090 additions & 0 deletions config/crd/bases/cdap.cdap.io_cdapmasters.yaml

Large diffs are not rendered by default.

14 changes: 10 additions & 4 deletions controllers/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func buildStatefulSets(master *v1alpha1.CDAPMaster, name string, services Servic
continue
}
env := addJavaMaxHeapEnvIfNotPresent(ss.Env, ss.Resources)
c := newContainerSpec(master, s, dataDir).setResources(ss.Resources).setEnv(env)
c := newContainerSpec(master, s, dataDir).setResources(ss.Resources).setEnv(env).setLifecycle(ss.Lifecycle)
if s == serviceUserInterface {
c = updateSpecForUserInterface(master, c)
}
Expand Down Expand Up @@ -274,7 +274,7 @@ func buildDeployment(master *v1alpha1.CDAPMaster, name string, services ServiceG
continue
}
env := addJavaMaxHeapEnvIfNotPresent(ss.Env, ss.Resources)
c := newContainerSpec(master, s, dataDir).setResources(ss.Resources).setEnv(env)
c := newContainerSpec(master, s, dataDir).setResources(ss.Resources).setEnv(env).setLifecycle(ss.Lifecycle)
if s == serviceUserInterface {
c = updateSpecForUserInterface(master, c)
}
Expand Down Expand Up @@ -339,7 +339,7 @@ func buildStatefulSetsObject(spec *StatefulSpec) (*reconciler.Object, error) {
if err != nil {
return nil, err
}
// For custom volumes and custom volume mounts, we directly pass structs from the spec to bypass the YAML templating logic.
// For container lifecycle hook, custom volumes, and custom volume mounts, we directly pass structs from the spec to bypass the YAML templating logic.
k8sObj, ok := obj.Obj.(*k8s.Object)
if !ok {
return nil, fmt.Errorf("failed to convert object to k8s object")
Expand All @@ -360,6 +360,7 @@ func buildStatefulSetsObject(spec *StatefulSpec) (*reconciler.Object, error) {
if err := addVolumeMountToContainer(&statefulSetObj.Spec.Template.Spec.Containers[index], spec.Base.AdditionalVolumeMounts); err != nil {
return nil, err
}
setLifecycleHookForContainer(&statefulSetObj.Spec.Template.Spec.Containers[index], spec.Containers[index].Lifecycle)
}
return obj, nil
}
Expand All @@ -370,7 +371,7 @@ func buildDeploymentObject(spec *DeploymentSpec) (*reconciler.Object, error) {
if err != nil {
return nil, err
}
// For custom volumes and volume mounts, we directly pass structs from the spec to bypass the YAML templating logic.
// For container lifecycle hook, custom volumes, and volume mounts, we directly pass structs from the spec to bypass the YAML templating logic.
k8sObj, ok := obj.Obj.(*k8s.Object)
if !ok {
return nil, fmt.Errorf("failed to convert object to k8s object")
Expand All @@ -391,6 +392,7 @@ func buildDeploymentObject(spec *DeploymentSpec) (*reconciler.Object, error) {
if err := addVolumeMountToContainer(&deploymentObj.Spec.Template.Spec.Containers[index], spec.Base.AdditionalVolumeMounts); err != nil {
return nil, err
}
setLifecycleHookForContainer(&deploymentObj.Spec.Template.Spec.Containers[index], spec.Containers[index].Lifecycle)
}
return obj, nil
}
Expand Down Expand Up @@ -419,6 +421,10 @@ func addVolumeMountToContainer(container *corev1.Container, volumeMountsToAdd []
return nil
}

func setLifecycleHookForContainer(container *corev1.Container, lifecycle *corev1.Lifecycle) {
container.Lifecycle = lifecycle
}

// Return a NodePort service to expose the supplied target service
func buildNetworkService(master *v1alpha1.CDAPMaster, name NetworkServiceName, target ServiceName, labels map[string]string) (*NetworkServiceSpec, error) {
s, err := getCDAPExternalServiceSpec(master, target)
Expand Down
6 changes: 6 additions & 0 deletions controllers/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type ContainerSpec struct {
ResourceRequests map[string]*resource.Quantity `json:"resourceRequests,omitempty"`
ResourceLimits map[string]*resource.Quantity `json:"resourceLimits,omitempty"`
DataDir string `json:"dataDir,omitempty"`
Lifecycle *corev1.Lifecycle `json:"lifecycle,omitempty"`
}

func newContainerSpec(master *v1alpha1.CDAPMaster, name, dataDir string) *ContainerSpec {
Expand Down Expand Up @@ -120,6 +121,11 @@ func (s *ContainerSpec) setResources(resources *corev1.ResourceRequirements) *Co
return s
}

func (s *ContainerSpec) setLifecycle(lifecycle *corev1.Lifecycle) *ContainerSpec {
s.Lifecycle = lifecycle
return s
}

// BaseSpec contains command fields for both StatefulSet and Deployment
type BaseSpec struct {
Name string `json:"name,omitempty"`
Expand Down
7 changes: 7 additions & 0 deletions controllers/testdata/appfabric.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@
"privileged": false,
"readOnlyRootFilesystem": false
},
"lifecycle": {
"preStop": {
"exec": {
"command": ["sh", "-c", "echo hello"]
}
}
},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
Expand Down
9 changes: 8 additions & 1 deletion controllers/testdata/cdap_master_cr.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,14 @@
"name": "test-persistent-storage",
"mountPath": "/mnt/teststorage"
}
]
],
"lifecycle": {
"preStop": {
"exec": {
"command": ["sh", "-c", "echo hello"]
}
}
}
},
"authentication": {
"metadata": {
Expand Down
6 changes: 6 additions & 0 deletions templates/cdap-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
#
#
# NOTE: Some properties are highly nested and it is not feasible to pick them from the template file
# hence those are added directly in the code.
# For example, please check the method "../controllers/deployment.go#buildDeploymentObject" and see
# how container's lifecycle property is added to the k8s object.
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down
6 changes: 6 additions & 0 deletions templates/cdap-sts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
#
#
# NOTE: Some properties are highly nested and it is not feasible to pick them from the template file
# hence those are added directly in the code.
# For example, please check the method "../controllers/deployment.go#buildStatefulSetsObject" and see
# how container's lifecycle property is added to the k8s object.
apiVersion: apps/v1
kind: StatefulSet
metadata:
Expand Down