diff --git a/README.md b/README.md index 65834b5..4029bc6 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,6 @@ To know more about LitmusChaos experiments [refer](https://litmuschaos.github.io - Now fork and clone [chaos-charts](https://github.com/litmuschaos/chaos-charts), Enter into [workflow](https://github.com/litmuschaos/chaos-charts/tree/master/workflows) directory. - Enter into `charts` directory to add charts which has been generated using sdk, for [reference](https://github.com/litmuschaos/chaos-charts/tree/master/charts/cassandra) - Enter into `workflow` directory and add workflow manifests for [reference](https://github.com/litmuschaos/chaos-charts/tree/master/workflows/podtato-head) - - **Note**: Update `sample_category` and `sample_exec_chaos` to `sample-category` and `sample-exec-chaos` inside manifest in every chart name while updating chaos-charts. Example: `sample_category.package.yaml` to `sample-category.package.yaml` - Connect your Git repository with chaos-center [ChaosHub](https://docs.litmuschaos.io/docs/concepts/chaoshub/) - Workflow can be added as a predefined workflow in Github and users can test by following the given steps: - Fork and clone [chaos-charts](https://github.com/litmuschaos/chaos-charts), now Enter into [workflow](https://github.com/litmuschaos/chaos-charts/tree/master/workflows) directory. diff --git a/contribute/developer-guide/README.md b/contribute/developer-guide/README.md index 96c0447..a7fa489 100644 --- a/contribute/developer-guide/README.md +++ b/contribute/developer-guide/README.md @@ -145,9 +145,9 @@ scaffolded files consist of placeholders which can then be filled as desired. $ ls -ltr sample_category/charts total 24 - -rw-rw-r-- 1 oumkale oumkale 144 Jul 7 18:48 sample_category.package.yaml - -rw-rw-r-- 1 oumkale oumkale 848 Jul 7 18:48 sample_category.category_chartserviceversion.yaml - -rw-rw-r-- 1 oumkale oumkale 989 Jul 7 18:48 sample_exec_chaos.experiment_chartserviceversion.yaml + -rw-rw-r-- 1 oumkale oumkale 144 Jul 7 18:48 sample-category.package.yaml + -rw-rw-r-- 1 oumkale oumkale 848 Jul 7 18:48 sample-category.chartserviceversion.yaml + -rw-rw-r-- 1 oumkale oumkale 989 Jul 7 18:48 sample-exec-chaos.chartserviceversion.yaml -rw-rw-r-- 1 oumkale oumkale 1540 Jul 7 18:48 experiment.yaml -rw-rw-r-- 1 oumkale oumkale 1224 Jul 7 18:48 rbac.yaml -rw-rw-r-- 1 oumkale oumkale 731 Jul 7 18:48 engine.yaml @@ -220,7 +220,6 @@ Follow the steps provided below to setup okteto & test the experiment execution. This should take you to the bash prompt on the dev container into which the content of the litmus-python repo is loaded. - Note : - - Replace `_` in chart manifest with `-` ex: sample_category to sample-category. Don't replace in directory name. - Add packages routes for all the files which are generated from sdk in `setup.py` before creating image. example : ``` diff --git a/contribute/developer-guide/generate_experiment.py b/contribute/developer-guide/generate_experiment.py index 62bc750..767a399 100644 --- a/contribute/developer-guide/generate_experiment.py +++ b/contribute/developer-guide/generate_experiment.py @@ -11,57 +11,66 @@ def generate_init(init_path): init_path = init_path + '/' + '__init__.py' open(init_path, mode='a').close() + # generate_csv creates the experiment chartserviceversion manifest def generate_csv(csv_parent_path, csv_name, csv_config, litmus_env): - - csv_filename = csv_parent_path + '/' + csv_name + '.' + 'experiment_chartserviceversion.yaml' + csv_filename = csv_parent_path + '/' + csv_name + '.chartserviceversion.yaml' # Load Jinja2 template - template = litmus_env.get_template('./templates/experiment_chartserviceversion.tmpl') + template = litmus_env.get_template('./templates/experiment-chartserviceversion.tmpl') output_from_parsed_template = template.render(csv_config) + with open(csv_filename, "w") as f: f.write(output_from_parsed_template) + # generate_csv creates the category chartserviceversion manifest def generate_csv_cat(csv_parent_path, csv_name, csv_config, litmus_env): - - csv_filename = csv_parent_path + '/' + csv_name + '.' + 'category_chartserviceversion.yaml' + csv_filename = csv_parent_path + '/' + csv_name + '.chartserviceversion.yaml' # Load Jinja2 template - template = litmus_env.get_template('./templates/category_chartserviceversion.tmpl') + template = litmus_env.get_template('./templates/category-chartserviceversion.tmpl') output_from_parsed_template = template.render(csv_config) + with open(csv_filename, "w") as f: f.write(output_from_parsed_template) + # generate_chart creates the experiment custom resource manifest def generate_chart(chart_parent_path, chart_config, litmus_env): chart_filename = chart_parent_path + '/' + 'experiment.yaml' # Load Jinja2 template - template = litmus_env.get_template('./templates/experiment_custom_resource.tmpl') + template = litmus_env.get_template('./templates/experiment-custom-resource.tmpl') output_from_parsed_template = template.render(chart_config) + with open(chart_filename, "w") as f: f.write(output_from_parsed_template) + # generate_rbac creates the rbac for the experiment def generate_rbac(chart_parent_path, chart_config, litmus_env): rbac_filename = chart_parent_path + '/' + 'rbac.yaml' # Load Jinja2 template - template = litmus_env.get_template('./templates/experiment_rbac.tmpl') + template = litmus_env.get_template('./templates/experiment-rbac.tmpl') output_from_parsed_template = template.render(chart_config) + with open(rbac_filename, "w") as f: f.write(output_from_parsed_template) + # generate_engine creates the chaos engine for the experiment def generate_engine(chart_parent_path, chart_config, litmus_env): engine_filename = chart_parent_path + '/' + 'engine.yaml' # Load Jinja2 template - template = litmus_env.get_template('./templates/experiment_engine.tmpl') + template = litmus_env.get_template('./templates/experiment-engine.tmpl') output_from_parsed_template = template.render(chart_config) + with open(engine_filename, "w") as f: f.write(output_from_parsed_template) + # generate_chaoslib creates the chaosLib for the experiment def generate_chaoslib(chaoslib_parent_path, chaoslib_name, chaoslib_config, litmus_env): chaoslib_filename = chaoslib_parent_path + '/' + chaoslib_name + '.py' @@ -71,12 +80,14 @@ def generate_chaoslib(chaoslib_parent_path, chaoslib_name, chaoslib_config, litm # Load Jinja2 template template = litmus_env.get_template('./templates/chaoslib.tmpl') output_from_parsed_template = template.render(chaoslib_config) + with open(chaoslib_filename, "w") as f: f.write(output_from_parsed_template) # generate __init__.py file generate_init(chaoslib_parent_path) + # generate_environment creates the environment for the experiment def generate_environment(environment_parent_path, environment_config, litmus_env): environment_filename = environment_parent_path + '/environment.py' @@ -86,12 +97,14 @@ def generate_environment(environment_parent_path, environment_config, litmus_env # Load Jinja2 template template = litmus_env.get_template('./templates/environment.tmpl') output_from_parsed_template = template.render(environment_config) + with open(environment_filename, "w") as f: f.write(output_from_parsed_template) # generate __init__.py file generate_init(environment_parent_path) + # generate_types creates the types.py for the experiment def generate_types(types_parent_path, types_config, litmus_env): types_filename = types_parent_path + '/types.py' @@ -101,22 +114,26 @@ def generate_types(types_parent_path, types_config, litmus_env): # Load Jinja2 template template = litmus_env.get_template('./templates/types.tmpl') output_from_parsed_template = template.render(types_config) + with open(types_filename, "w") as f: f.write(output_from_parsed_template) # generate __init__.py file generate_init(types_parent_path) + # generate_k8s_deployment creates the experiment kubernetes deployment manifest def generate_k8s_deployment(k8s_parent_path, k8s_config, litmus_env): k8s_filename = k8s_parent_path + '/' + 'test.yml' # Load Jinja2 template - template = litmus_env.get_template('./templates/experiment_k8s_deployment.tmpl') + template = litmus_env.get_template('./templates/experiment-k8s-deployment.tmpl') output_from_parsed_template = template.render(k8s_config) + with open(k8s_filename, "w") as f: f.write(output_from_parsed_template) + # generate_experiment creates the expriment.py file def generate_experiment(experiment_parent_path, experiment_name, experiment_config, litmus_env): experiment_filename = experiment_parent_path + '/' + experiment_name + '.py' @@ -124,12 +141,14 @@ def generate_experiment(experiment_parent_path, experiment_name, experiment_conf # Load Jinja2 template template = litmus_env.get_template('./templates/experiment.tmpl') output_from_parsed_template = template.render(experiment_config) + with open(experiment_filename, "w+") as f: f.write(output_from_parsed_template) # generate __init__.py file generate_init(experiment_parent_path) + # generate_package creates the package manifest def generate_package(package_parent_path, config, package_name, litmus_env): package_filename = package_parent_path + '/' + package_name + '.package.yaml' @@ -137,15 +156,18 @@ def generate_package(package_parent_path, config, package_name, litmus_env): # Load Jinja2 template template = litmus_env.get_template('./templates/package.tmpl') output_package = template.render(config) + with open(package_filename, "w") as f: f.write(output_package) + # create_dir create new directory def create_dir(path): if os.path.isdir(path) != True: os.makedirs(path) -def generate_icon(chart_parent_path, litmus_root, image_name, litmus_env): + +def generate_icon(chart_parent_path, litmus_root, image_name): src_dir = litmus_root + "/contribute/developer-guide/icons/" dst_dir = chart_parent_path + '/' + "icons/" create_dir(dst_dir) @@ -154,6 +176,7 @@ def generate_icon(chart_parent_path, litmus_root, image_name, litmus_env): shutil.copy(jpgfile, dst_dir) os.rename(dst_dir + '/' + 'k8s.png', dst_dir + '/' + image_name +'.png') + def main(): parser = argparse.ArgumentParser() @@ -178,6 +201,13 @@ def main(): # get name and category entity_name = config['name'] category_name = config['category'] + + # Replace underscore (_) with hyphen (-) + # in entity_name_yaml and category_name_yaml + # for chart filenames and k8s objects + # like service-accounts, chart file names etc. + entity_name_k8s = entity_name.replace("_", "-") + category_name_k8s = category_name.replace("_", "-") env = Environment(loader = FileSystemLoader('./'), trim_blocks=True, lstrip_blocks=True, autoescape=select_autoescape(['yaml'])) @@ -185,10 +215,13 @@ def main(): litmus_root = os.path.abspath(os.path.join("..", os.pardir)) # initilise directories - exp_root_dir = litmus_root + '/experiments/' + '/' + config['category'] + exp_root_dir = litmus_root + '/experiments/' + '/' + category_name create_dir(exp_root_dir) - experiment_root_dir = exp_root_dir + '/' + config['name'] + + experiment_root_dir = exp_root_dir + '/' + entity_name create_dir(experiment_root_dir) + + # Generate init files generate_init(exp_root_dir) # if generate_type is chart, only generate the chart(top)-level CSV & package manifests @@ -201,21 +234,21 @@ def main(): if chartType == "category" or chartType == "all": # generate icon for category - generate_icon(chart_dir, litmus_root, category_name, env) + generate_icon(chart_dir, litmus_root, category_name_k8s) # generate category chartserviceversion - generate_csv_cat(chart_dir, category_name, config, env) + generate_csv_cat(chart_dir, category_name_k8s, config, env) # generate package - generate_package(chart_dir, config, category_name, env) + generate_package(chart_dir, config, category_name_k8s, env) if chartType == "experiment" or chartType == "all": # generate icon for category - generate_icon(chart_dir, litmus_root, entity_name, env) + generate_icon(chart_dir, litmus_root, entity_name_k8s) # generate experiment charts - generate_csv(chart_dir, entity_name, config, env) + generate_csv(chart_dir, entity_name_k8s, config, env) # generate experiment-custom-resource generate_chart(chart_dir, config, env) @@ -245,13 +278,13 @@ def main(): generate_init(experiment_root_dir) # initialise chaosLib, environment and types directory - chaoslib_dir = litmus_root + '/chaosLib/litmus/' + config['name'] + '/lib' - environment_dir = litmus_root + '/pkg/' + config['category'] + '/environment' - types_dir = litmus_root + '/pkg/' + config['category'] + '/types' + chaoslib_dir = litmus_root + '/chaosLib/litmus/' + entity_name + '/lib' + environment_dir = litmus_root + '/pkg/' + category_name + '/environment' + types_dir = litmus_root + '/pkg/' + category_name + '/types' # create and generate __init__.py file in chaosLib experiment dir - create_dir(litmus_root + '/chaosLib/litmus/' + config['name']) - generate_init(litmus_root + '/chaosLib/litmus/' + config['name']) + create_dir(litmus_root + '/chaosLib/litmus/' + entity_name) + generate_init(litmus_root + '/chaosLib/litmus/' + entity_name) # generate experiment.py generate_experiment(experiment_dir, entity_name, config, env) @@ -268,7 +301,7 @@ def main(): # generate k8s deployment generate_k8s_deployment(test_dir, config, env) - generate_init(litmus_root + '/pkg/' + config['category']) + generate_init(litmus_root + '/pkg/' + category_name) print("experiment created successfully") else: diff --git a/contribute/developer-guide/templates/category_chartserviceversion.tmpl b/contribute/developer-guide/templates/category-chartserviceversion.tmpl similarity index 60% rename from contribute/developer-guide/templates/category_chartserviceversion.tmpl rename to contribute/developer-guide/templates/category-chartserviceversion.tmpl index a6b25d3..26f0d41 100644 --- a/contribute/developer-guide/templates/category_chartserviceversion.tmpl +++ b/contribute/developer-guide/templates/category-chartserviceversion.tmpl @@ -1,34 +1,34 @@ apiVersion: litmuchaos.io/v1alpha1 kind: ChartServiceVersion metadata: - name: {{ category }} + name: {{ category | replace("_", "-") }} version: {{ version }} annotations: - categories: {{ category }} + categories: {{ category | replace("_", "-") }} spec: - displayName: {{ ccategory }} chaos + displayName: {{ category | replace("_", "-") }} chaos categoryDescription: > {{ description }} experiments: - - {{ name }} + - {{ name | replace("_", "-") }} keywords: {%- for key in keywords %} - "{{ key }}" {%- endfor %} maintainers: {%- for i in maintainers %} - - name: {{- i.name }} - email: {{- i.email }} + - name: {{ i.name }} + email: {{ i.email }} {%- endfor %} minKubeVersion: {{ minkubernetesversion }} provider: name: {{ provider.name }} links: {%- for ref in references %} - - name: {{- ref.name }} - url: {{- ref.url }} + - name: {{ ref.name }} + url: {{ ref.url }} {%- endfor %} icon: - url: mediatype: "" - chaosexpcrdlink: https://raw.githubusercontent.com/litmuschaos/chaos-charts/master/charts/{{ category }}/experiments.yaml \ No newline at end of file + chaosexpcrdlink: https://raw.githubusercontent.com/litmuschaos/chaos-charts/master/charts/{{ category | replace("_", "-") }}/experiments.yaml \ No newline at end of file diff --git a/contribute/developer-guide/templates/environment.tmpl b/contribute/developer-guide/templates/environment.tmpl index 6c6e7d6..58d9d39 100644 --- a/contribute/developer-guide/templates/environment.tmpl +++ b/contribute/developer-guide/templates/environment.tmpl @@ -5,7 +5,7 @@ import pkg.maths.maths as maths #GetENV fetches all the env variables from the runner pod def GetENV(experimentDetails): - experimentDetails.ExperimentName = os.getenv("EXPERIMENT_NAME", "pod-delete") + experimentDetails.ExperimentName = os.getenv("EXPERIMENT_NAME", "{{ name | replace("_", "-") }}") experimentDetails.ChaosNamespace = os.getenv("CHAOS_NAMESPACE", "litmus") experimentDetails.EngineName = os.getenv("CHAOSENGINE", "") experimentDetails.ChaosDuration = maths.atoi(os.getenv("TOTAL_CHAOS_DURATION", "30")) diff --git a/contribute/developer-guide/templates/experiment_chartserviceversion.tmpl b/contribute/developer-guide/templates/experiment-chartserviceversion.tmpl similarity index 68% rename from contribute/developer-guide/templates/experiment_chartserviceversion.tmpl rename to contribute/developer-guide/templates/experiment-chartserviceversion.tmpl index 3216d1e..8f6dc50 100644 --- a/contribute/developer-guide/templates/experiment_chartserviceversion.tmpl +++ b/contribute/developer-guide/templates/experiment-chartserviceversion.tmpl @@ -1,12 +1,12 @@ apiVersion: litmuchaos.io/v1alpha1 kind: ChartServiceVersion metadata: - name: {{ name }} + name: {{ name | replace("_", "-") }} version: {{ version }} annotations: - categories: {{ category }} + categories: {{ category | replace("_", "-") }} spec: - displayName: {{ name }} + displayName: {{ name | replace("_", "-") }} categoryDescription: > {{ description }} keywords: @@ -20,8 +20,8 @@ spec: maturity: {{ maturity }} maintainers: {%- for i in maintainers %} - - name: {{- i.name }} - email: {{- i.email }} + - name: {{ i.name }} + email: {{ i.email }} {%- endfor %} minKubeVersion: {{ minkubernetesversion }} provider: @@ -31,10 +31,10 @@ spec: app.kubernetes.io/version: latest links: {%- for ref in references %} - - name: {{- ref.name }} - url: {{- ref.url }} + - name: {{ ref.name }} + url: {{ ref.url }} {%- endfor %} icon: - url: mediatype: "" - chaosexpcrdlink: https://raw.githubusercontent.com/litmuschaos/chaos-charts/master/charts/{{ category }}/{{ name }}/experiment.yaml \ No newline at end of file + chaosexpcrdlink: https://raw.githubusercontent.com/litmuschaos/chaos-charts/master/charts/{{ category | replace("_", "-") }}/{{ name | replace("_", "-") }}/experiment.yaml \ No newline at end of file diff --git a/contribute/developer-guide/templates/experiment_custom_resource.tmpl b/contribute/developer-guide/templates/experiment-custom-resource.tmpl similarity index 85% rename from contribute/developer-guide/templates/experiment_custom_resource.tmpl rename to contribute/developer-guide/templates/experiment-custom-resource.tmpl index c47a01f..3fc2b76 100644 --- a/contribute/developer-guide/templates/experiment_custom_resource.tmpl +++ b/contribute/developer-guide/templates/experiment-custom-resource.tmpl @@ -4,9 +4,9 @@ description: {{ description }} kind: ChaosExperiment metadata: - name: {{ name }} + name: {{ name | replace("_", "-") }} labels: - name: {{ name }} + name: {{ name | replace("_", "-") }} app.kubernetes.io/part-of: litmus app.kubernetes.io/component: chaosexperiment app.kubernetes.io/version: latest @@ -32,7 +32,7 @@ spec: imagePullPolicy: Always args: - -c - - python3 -u experiment + - python3 -u experiment -name {{ name | replace("_", "-") }} command: - /bin/bash env: @@ -50,7 +50,7 @@ spec: value: '' labels: - name: {{ name }} + name: {{ name | replace("_", "-") }} app.kubernetes.io/part-of: litmus app.kubernetes.io/component: experiment-job app.kubernetes.io/version: latest diff --git a/contribute/developer-guide/templates/experiment_engine.tmpl b/contribute/developer-guide/templates/experiment-engine.tmpl similarity index 62% rename from contribute/developer-guide/templates/experiment_engine.tmpl rename to contribute/developer-guide/templates/experiment-engine.tmpl index 32a5f8c..378ca56 100644 --- a/contribute/developer-guide/templates/experiment_engine.tmpl +++ b/contribute/developer-guide/templates/experiment-engine.tmpl @@ -11,11 +11,11 @@ spec: engineState: 'active' #ex. values: ns1:name=percona,ns2:run=nginx auxiliaryAppInfo: '' - chaosServiceAccount: {{ name }}-sa + chaosServiceAccount: {{ name | replace("_", "-") }}-sa # It can be delete/retain jobCleanUpPolicy: 'delete' experiments: - - name: {{ name }} + - name: {{ name | replace("_", "-") }} spec: components: env: @@ -26,4 +26,15 @@ spec: # set chaos interval (in sec) as desired - name: CHAOS_INTERVAL value: '10' - \ No newline at end of file + + # provide application namespace + - name: APP_NAMESPACE + value: '' + + # provide application labels + - name: APP_LABEL + value: '' + + # provide application kind + - name: APP_KIND + value: '' \ No newline at end of file diff --git a/contribute/developer-guide/templates/experiment_k8s_deployment.tmpl b/contribute/developer-guide/templates/experiment-k8s-deployment.tmpl similarity index 96% rename from contribute/developer-guide/templates/experiment_k8s_deployment.tmpl rename to contribute/developer-guide/templates/experiment-k8s-deployment.tmpl index 6e796f1..d76982f 100644 --- a/contribute/developer-guide/templates/experiment_k8s_deployment.tmpl +++ b/contribute/developer-guide/templates/experiment-k8s-deployment.tmpl @@ -13,7 +13,7 @@ spec: labels: app: litmus-experiment spec: - serviceAccountName: {{ name }}-sa + serviceAccountName: {{ name | replace("_", "-") }}-sa containers: - name: gotest image: busybox diff --git a/contribute/developer-guide/templates/experiment_rbac.tmpl b/contribute/developer-guide/templates/experiment-rbac.tmpl similarity index 63% rename from contribute/developer-guide/templates/experiment_rbac.tmpl rename to contribute/developer-guide/templates/experiment-rbac.tmpl index cace00c..e4ebadb 100644 --- a/contribute/developer-guide/templates/experiment_rbac.tmpl +++ b/contribute/developer-guide/templates/experiment-rbac.tmpl @@ -2,19 +2,19 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: {{ name }}-sa + name: {{ name | replace("_", "-") }}-sa namespace: default labels: - name: {{ name }}-sa + name: {{ name | replace("_", "-") }}-sa app.kubernetes.io/part-of: litmus --- -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - name: {{ name }}-sa + name: {{ name | replace("_", "-") }}-sa namespace: default labels: - name: {{ name }}-sa + name: {{ name | replace("_", "-") }}-sa app.kubernetes.io/part-of: litmus rules: {% for per in permissions %} @@ -32,19 +32,19 @@ rules: {%- endfor %} {% endfor %} --- -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: {{ name }}-sa + name: {{ name | replace("_", "-") }}-sa namespace: default labels: - name: {{ name }}-sa + name: {{ name | replace("_", "-") }}-sa app.kubernetes.io/part-of: litmus roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: {{ name }}-sa + name: {{ name | replace("_", "-") }}-sa subjects: - kind: ServiceAccount - name: {{ name }}-sa + name: {{ name | replace("_", "-") }}-sa namespace: default \ No newline at end of file diff --git a/contribute/developer-guide/templates/package.tmpl b/contribute/developer-guide/templates/package.tmpl index 900b068..3a78149 100644 --- a/contribute/developer-guide/templates/package.tmpl +++ b/contribute/developer-guide/templates/package.tmpl @@ -1,5 +1,5 @@ -packageName: {{ category }} +packageName: {{ category | replace("_", "-") }} experiments: - - name: {{ name }} - CSV: {{ name }}.chartserviceversion.yaml - desc: "{{ name }}" \ No newline at end of file + - name: {{ name | replace("_", "-") }} + CSV: {{ name | replace("_", "-") }}.chartserviceversion.yaml + desc: "{{ name | replace("_", "-") }}" \ No newline at end of file diff --git a/contribute/developer-guide/templates/types.tmpl b/contribute/developer-guide/templates/types.tmpl index ae28f1f..9c680df 100644 --- a/contribute/developer-guide/templates/types.tmpl +++ b/contribute/developer-guide/templates/types.tmpl @@ -21,6 +21,6 @@ class ExperimentDetails(object): self.TargetPods = TargetPods self.PodsAffectedPerc = PodsAffectedPerc self.LIBImagePullPolicy = LIBImagePullPolicy - self.ChaosInjectCmd = ChaosInjectCmd + self.ChaosInjectCmd = ChaosInjectCmd self.ChaosKillCmd = ChaosKillCmd self.TargetContainer = TargetContainer