├── .vscode └── settings.json ├── 000-index.md ├── 010-case-structure.md ├── 100-case.md ├── 110-roles.md ├── 120-prereqs.md ├── 130-certification.md ├── 140-resource-groups.md ├── 200-inventory.md ├── 210-resources.md ├── 220-actions.md ├── 300-signature.md ├── 310-digests.md ├── 400-archive.md ├── 500-repository.md ├── LICENSE ├── README.md ├── design ├── case-overview-olm-sig-20200121.pptx ├── case-resource-retrieval.drawio.png ├── case-signature-flow-diagram.png └── case.png ├── samples ├── case-repo-sample │ ├── etcd-operator-case │ │ ├── 1.0.0 │ │ │ ├── etcd-operator-case-1.0.0.tgz │ │ │ └── version.yaml │ │ └── index.yaml │ └── index.yaml ├── etcd-operator-case-flattened.yaml └── etcd-operator-case │ ├── LICENSE │ ├── README.md │ ├── case.yaml │ ├── certifications │ └── ibmccs.yaml │ ├── digests.yaml │ ├── inventory │ ├── clusterSetup │ │ ├── README.md │ │ ├── actions.yaml │ │ ├── files │ │ │ ├── etcd-resources │ │ │ │ ├── etcd-operator-clusterrole.yaml │ │ │ │ ├── etcd-operator-psp-clusterrole.yaml │ │ │ │ ├── etcd-operator-psp.yaml │ │ │ │ ├── etcd-operator-scc.yaml │ │ │ │ ├── etcdbackups-crd.yaml │ │ │ │ ├── etcdclusters-crd.yaml │ │ │ │ └── etcdrestores-crd.yaml │ │ │ └── install.sh │ │ ├── inventory.yaml │ │ └── resources.yaml │ ├── etcdBackupExample │ │ ├── README.md │ │ ├── actions.yaml │ │ ├── files │ │ │ └── etcdBackupExample.yaml │ │ ├── inventory.yaml │ │ └── resources.yaml │ ├── etcdClusterExample │ │ ├── README.md │ │ ├── actions.yaml │ │ ├── files │ │ │ └── etcdClusterExample.yaml │ │ ├── inventory.yaml │ │ └── resources.yaml │ ├── etcdOLMOperators │ │ ├── README.md │ │ ├── actions.yaml │ │ ├── files │ │ │ ├── catalogsource.yaml │ │ │ └── etcd-cluster-subscription.yaml │ │ ├── inventory.yaml │ │ └── resources.yaml │ ├── etcdOperators │ │ ├── README.md │ │ ├── actions.yaml │ │ ├── inventory.yaml │ │ └── resources.yaml │ ├── etcdRestoreExample │ │ ├── README.md │ │ ├── actions.yaml │ │ ├── files │ │ │ └── etcdRestoreExample.yaml │ │ ├── inventory.yaml │ │ └── resources.yaml │ ├── loadAirgapResources │ │ ├── README.md │ │ ├── actions.yaml │ │ ├── files │ │ │ └── parse_csv.sh │ │ ├── inventory.yaml │ │ └── resources.yaml │ ├── namespaceSetup │ │ ├── README.md │ │ ├── actions.yaml │ │ ├── files │ │ │ ├── namespace.yaml │ │ │ ├── rolebinding.yaml │ │ │ ├── scc.sh │ │ │ └── service-account.yaml │ │ ├── inventory.yaml │ │ └── resources.yaml │ └── productInstall │ │ ├── README.md │ │ ├── actions.yaml │ │ ├── files │ │ └── install.sh │ │ ├── inventory.yaml │ │ └── resources.yaml │ ├── licenses │ └── LICENSE │ ├── prereqs.yaml │ └── roles.yaml ├── schema ├── actions.json ├── case.json ├── certification.json ├── digests.json ├── inventory.json ├── logical-grammar.json ├── metadata.json ├── prereqs.json ├── repo-index.json ├── repo-product-index.json ├── repo-product-version.json ├── resource-groups.json ├── resources.json ├── roles.json ├── signature.json └── version.json └── utilities ├── createArchive.sh └── processFiles.sh /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "yaml.schemas": { 3 | "./schema/case.json": "case.yaml", 4 | "./schema/inventory.json": "inventory.yaml", 5 | "./schema/prereqs.json": "prereqs.yaml", 6 | "./schema/certification.json": "certifications/*.yaml", 7 | "./schema/roles.json": "roles.yaml", 8 | "./schema/resources.json": "resources.yaml", 9 | "./schema/actions.json": "actions.yaml", 10 | "./schema/digests.json": "digests.yaml", 11 | "./schema/repo-index.json": "samples/case-repo-sample/index.yaml", 12 | "./schema/repo-product-index.json": "samples/case-repo-sample/etcd-operator-case/index.yaml", 13 | "./schema/repo-product-version.json": "version.yaml" 14 | } 15 | } -------------------------------------------------------------------------------- /000-index.md: -------------------------------------------------------------------------------- 1 | # Container Application Software for Enterprises (CASE) Specification Index 2 | 3 | * [Overall CASE Structure, Conventions and Overview](010-case-structure.md) 4 | * [CASE YAML and Object](100-case.md) 5 | * [CASE Roles YAML and Object](110-roles.md) 6 | * [CASE Prereqs YAML and Object](120-prereqs.md) 7 | * [CASE Certification YAML and Object](130-certification.md) 8 | * [CASE Inventory Items](200-inventory.md) 9 | * [CASE Inventory Resources YAML and Object](210-resources.md) 10 | * [CASE Inventory Actions YAML and Object](220-actions.md) 11 | * [CASE Signature YAML and Object](300-signature.md) 12 | * [CASE digests.yaml Specification](310-digests.md) 13 | * [CASE Archive](400-archive.md) 14 | * [CASE Repository](500-repository.md) 15 | 16 | -------------------------------------------------------------------------------- /010-case-structure.md: -------------------------------------------------------------------------------- 1 | # CASE Directory and File Structure Specification 2 | 3 | - [CASE Directory and File Structure Specification](#case-directory-and-file-structure-specification) 4 | - [Status: Stable](#status-stable) 5 | - [Overview](#overview) 6 | - [Specification](#specification) 7 | - [Files and Folders](#files-and-folders) 8 | - [YAML File Format](#yaml-file-format) 9 | - [Canonical Flat CASE Format](#canonical-flat-case-format) 10 | - [Specification metadata and versioning](#specification-metadata-and-versioning) 11 | - [Entity References](#entity-references) 12 | - [Logical Operations](#logical-operations) 13 | - [Semver and Semver Comparision Formats](#semver-and-semver-comparision-formats) 14 | 15 | 16 | ## Status: Stable 17 | 18 | ## Overview 19 | 20 | ## Specification 21 | The CASE is a well defined file and directory structure. 22 | * Each folder MUST NOT include any other folders or files unless otherwise noted. 23 | 24 | ### Files and Folders 25 | The files described here are well named unless included in ``, in which a name is user-defined. 26 | ``` 27 | / # The name of the folder that encompasses the CASE. It must be named the same as the CASE. See the CASE name specification: 100-case.md for details. (Required) 28 | case.yaml # CASE descriptor YAML file. (Required) 29 | certifications/ # Certification information. (Optional) 30 | # One or more certification files. See the certification specification: 130-certification.md for details. (Required if folder exists) 31 | inventory/ # Directory of inventory items. One sub-directory per item. (Required) 32 | / # Directory of a single inventory item. (Required) 33 | Must include at least 1-N directories. 34 | inventory.yaml # The metadata that describes an inventory item. (Required) 35 | actions.yaml # The actions that can be performed on this inventory item. (Optional) 36 | README.md # Human readable documentation about the inventory item. (Required) 37 | resources.yaml # The metadata about each resource referenced or embedded with this inventory item. (Optional) 38 | files/ # Embedded files referenced in the resources.yaml. (Optional) 39 | README.md # Human readable documentation about the CASE. (Required) 40 | prereqs.yaml # Prerequisites and dependency references for the CASE inventory. (Required) 41 | roles.yaml # Roles required to apply actions on inventory items in the CASE. (Required) 42 | LICENSE # A text file with the contents of the Apache 2.0 license. (Required) 43 | licenses/ # UTF-8 encoded text file licenses that apply to the inventory items in the CASE if different from the CASE license. (Optional) 44 | signature.yaml # The digital signature that verifies the authenticity of the CASE. (Optional) 45 | ``` 46 | 47 | ### YAML File Format 48 | * All YAML files MUST follow the following rules: 49 | * YAML format must follow a subset of the [YAML v1.2 specification](https://yaml.org/spec/1.2/spec.html) as follows: 50 | * YAML must resolve to canonical JSON using the JSON Canonicalization Scheme (JCS) [draft-rundgren-json-canonicalization-scheme-00](https://github.com/cyberphone/json-canonicalization) 51 | * YAML must pass validation using the included JSONSchema file. 52 | * YAML file can include comments, but may be discarded by processing engines. 53 | * Fields and elements included in the YAML that are not included in the JSONSchema associated with the specification version defined in the `case.yaml` ARE NOT SUPPORTED and may be discarded or ignored. 54 | * Property names: 55 | * SHOULD be meaningful names with defined semantics. 56 | * MUST be camel-cased, ascii strings. 57 | * The first character MUST be a letter, an underscore (_) or a dollar sign ($). 58 | * Subsequent characters CAN be a letter, a digit, an underscore, or a dollar sign. 59 | * Reserved [JavaScript keywords](https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/ttyab5c8(v=vs.100)) should be avoided. 60 | * Maximum length MUST be 50 characters or less. 61 | 62 | ### Canonical Flat CASE Format 63 | Each YAML file includes a subset the of the CASE definition, which makes it easier to identify optional vs. required portions of the specification, and makes it easier for build processes and source control systems to organize the information. 64 | 65 | The overall format of the flattened CASE document is: 66 | ``` 67 | case: 68 | case: 69 | 70 | roles: 71 | 72 | prereqs: 73 | 74 | inventories: 75 | 76 | inventory: 77 | 78 | resources: 79 | 80 | actions: 81 | 82 | certifications: 83 | 84 | 85 | ``` 86 | 87 | See the included utility script [flattenCase.sh](utilities/flattenCase.sh) to produce a single YAML file. 88 | 89 | ### Specification metadata and versioning 90 | Each CASE object (e.g. roles) except for the top level CASE object itself, includes an optional `metadata` object. This object includes metadata about the object and what specification version it implements. 91 | 92 | The metadata object includes the following properties: 93 | * `specVersion`: The version of the specification that the enclosing object schema represents (optional). This is used as an override and should not normally be used. 94 | * `name`: The name of the object (optional). 95 | * `displayName`: The displayable name (optional). 96 | * `description`: The description of the object (optional). 97 | * `displayDescription`: The displayable description (optional). 98 | 99 | Additional properties MAY be added. To avoid collisions with future versions of the specification, use a unique prefix or the character prefix: `$` or `_` 100 | 101 | 102 | Example: 103 | ``` 104 | metadata: 105 | specVersion: 0.1. 106 | name: myResource 107 | displayName: My Resource 108 | description: This is My Resource... Additional notes about it here.... 109 | displayDescription: My Resource and more about it. 110 | _myInformation: 111 | buildVersion: 20191231 112 | ``` 113 | 114 | ### Entity References 115 | There are several YAML files that reference attributes from other entities in other YAML files. 116 | 117 | To reference an attribute or object within the same document or across documents: 118 | * Use the JSON Pointer format [RFC6901](https://tools.ietf.org/html/rfc6901) 119 | * Use the canonicalized (flattened) format of hte specification to locate the path of target entities. 120 | 121 | ### Logical Operations 122 | The logical operations will follow the [json-logic](http://jsonlogic.com/) model. So a json logic compliant yaml file like the following: 123 | ```yml 124 | and: 125 | - or: 126 | - "/prereqs/k8sDistros/ibmCloud" 127 | - "/prereqs/k8sDistros/ibmCloudPrivate" 128 | - "/prereqs/k8sDistros/openshift" 129 | - or: 130 | - and: 131 | - "!": # notice the quotes because ! represents a tag 132 | - "/prereqs/k8sDistros/openshift" 133 | - or: 134 | - "/prereqs/k8sResources/ibmRestrictedPSP" 135 | - "/prereqs/k8sResources/etcdControllerPSP" 136 | - and: 137 | - "/prereqs/k8sDistros/openshift" 138 | - or: 139 | - "/prereqs/k8sResources/ibmRestrictedSCC" 140 | - "/prereqs/k8sResources/etcdControllerSCC" 141 | ``` 142 | can be parsed into json. 143 | 144 | The logical operators and, or, not operate on a set of resolvers. So a boolean expression like `((A && B) || (!C && (E || F)))` would translate to: 145 | 146 | ```yml 147 | or: 148 | - and: 149 | - A 150 | - B 151 | - and: 152 | - not: 153 | - C 154 | - or: 155 | - E 156 | - F 157 | ``` 158 | 159 | ### Semver and Semver Comparision Formats 160 | This specification uses the [Semantic Version 2.0.0 specification](https://semver.org/) (semver) for describing versions of entities. 161 | -------------------------------------------------------------------------------- /100-case.md: -------------------------------------------------------------------------------- 1 | # CASE case.yaml Specification 2 | - [CASE case.yaml Specification](#case-caseyaml-specification) 3 | - [Status: Stable](#status-stable) 4 | - [Overview](#overview) 5 | - [Specification](#specification) 6 | - [`version`](#version) 7 | - [Regular expression](#regular-expression) 8 | - [version examples](#version-examples) 9 | - [appSemver vs version](#appsemver-vs-version) 10 | - [appSemver vs appVersion](#appsemver-vs-appversion) 11 | - [additionalVersions example](#additionalversions-example) 12 | - [`supports`](#supports) 13 | - [`architectures`](#architectures) 14 | - [`k8sDistros`](#k8sdistros) 15 | - [`managedPlatforms`](#managedplatforms) 16 | 17 | ## Status: Stable 18 | 19 | ## Overview 20 | The `case.yaml` file is a YAML document that follows the [CASE YAML rules](010-case-structure.md). The `case.yaml` is a base object that includes information about the CASE. 21 | 22 | ## Specification 23 | The `case.yaml` has the following attributes: 24 | * `specVersion`: The CASE specification version that this CASE instance implements (required String). For example: `1.0.0`. 25 | * `name`: The globally unique name of the CASE (required String) with the following limitations: 26 | * must be 50 characters or less 27 | * begin with a lower case character 28 | * contain alpha-numeric characters or the following special characters: `-_` 29 | * `displayName`: The human readable name of the CASE (optional String). 30 | * `appSemver`: The semantic version of the application in the CASE. 31 | * `version`: The Semver 2 version of the CASE (required String). This version must be updated each time a CASE is updated. See the [version documentation.](#version) 32 | * `appVersion`: The version of the application or product that this CASE represents. This value can be any string that matches the organization versioning standards. 33 | * `additionalVersions`: This is a listing of any additional versions the CASE may need to represent that is not included in the `version`, `appSemver` or `appVersion` fields. 34 | * `description`: The description of the CASE (required String). 35 | * `displayDescription`: The displayable description of the CASE (optional String). 36 | * `icons`: An array of encoded icon definitions for the project (optional) 37 | * `base64`: The base64 encoded binary representation of the image (PNG or SVG) (optional if url is specified) 38 | * `mediaType`: The media-type of the image. One of: `image/png` or `image/svg+xml` (required) 39 | * `url`: The URL of the image if not embedded. (optional if base64 is specified) 40 | * `organization`: The name of the organization/distributor of the CASE (String). 41 | * `certifications`: Summary of the certifications this CASE provides. Details are provided in the [certification.yaml](130-certification.md) file. 42 | * `supports`: Describes various levels of support for this CASE. (CASE Objects) See the [supports](#supports) section for details. 43 | * `architectures`: Compute [architectures](#architectures). (CASE Object) 44 | * `k8sDistros`: [Kubernetes distributions](#k8sdistros). (CASE Object) 45 | * `managedPlatforms`: [Managed platforms](#managedplatforms). (CASE Object) 46 | * `classifications`: The type of license or usage classifiers for this CASE. (CASE Objects) 47 | * `catalogs`: Catalog categories which this software applies to in a catalog. (CASE Objects) 48 | * `webPage`: The URL of the page that consumers can reference for additional information about this CASE. (String) 49 | * `licenses`: All of the licenses that pertain to the software in this CASE. 50 | * `` A license name e.g. apache2 (CASE Object) 51 | * `metadata`: Metadata about the licence. The `name` must match the license-key if provided. 52 | * `ref`: The relative path to the license in the `licenses` directory (Required) 53 | * `url`: A URL to the license. This must reference the same license as the `ref`. This may be used to link to translated licenses (Optional) 54 | * `mediaType`: The (MIME) media type of the license file. 55 | 56 | ### `version` 57 | A CASE typically represents a single product, but can be composed of many embedded components and products that collectively provide a version. CASE `version` extends semantic versioning in such a way that allows the CASE producer and consumer to quickly identify the scope of a functional or non-functional change. 58 | 59 | The format of the version in Backus-Naur Form, where several tokens are defined in [semver.org](https://semver.org/#backusnaur-form-grammar-for-valid-semver-versions). Please refer the semver.org documentation for definition of and . 60 | ``` 61 | ::= 62 | | "+" 63 | ::= "." "." 64 | ::= | 65 | "." 66 | ::= "." 67 | ``` 68 | 69 | The `version core` portion of the version is the typical semver `major.minor.patch` version semantic that descrbes the functional changes that the CASE product has implemented between this version an the previous version. The `version core` represents the ENTIRE CASE and all components and products within it. 70 | 71 | The `version non-functional` portion of the version is located in the first two tokens of the semver build section and is represented by a date/time in the gregorian calendar format: `YYYYMMDD.HHmmSS`, where: 72 | - `YYYY` is the year, 73 | - `MM` the month (including leading zero), 74 | - `DD` the day of the month (including leading zero), 75 | - `HH` the hour of the day (including leading zero), 76 | - `mm` the minute of the hour (including leading zero) 77 | - `ss` the second of the minute (including leading zero) 78 | 79 | Unlike semver, this specification applies precedence to the `version non-functional` portion of the build to allow sorting and retrieving the latest non-functional version within a given functional version. If the `version non-functional` value is not supplied, it is assumed to be equivalent to `000000.000000`. 80 | 81 | #### Regular expression 82 | 83 | The following JavaScript regular expressions show the difference between standard semver and a CASE version. 84 | 85 | https://regex101.com/r/i4ZyDs/1 86 | 87 | Standard semver: 88 | ``` 89 | ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*) 90 | (?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))? 91 | (?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ 92 | ``` 93 | 94 | CASE Semver 95 | ``` 96 | ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*) 97 | (?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))? 98 | (?:\+(\d{8}\.[0-2]\d[0-5]\d[0-5]\d)(?:\.(?:[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)? 99 | ``` 100 | 101 | #### version examples 102 | - Initial version without a build. 103 | 104 | `1.0.0` 105 | - Update the `README.md`. The two versions are functionally equivalent, but the latest version is: 106 | 107 | `1.0.0+20191008.070012` 108 | 109 | - Update the `prereqs.yaml` to add an additional Kubernetes distribution. There are now 3 functionally equivalent versions, but the latest version is: 110 | 111 | `1.0.0+20191008.162055` 112 | 113 | - Create a patch with a security fix with a custom build notation. The latest functional version is now: 114 | 115 | `1.0.1+20191009.070000.cve2019-1234` 116 | 117 | - Add a new feature. 118 | 119 | `1.1.0+20191115.070522` 120 | 121 | - Create a new version with API incompatibilities 122 | 123 | `2.0.0` 124 | 125 | - Bug fix/patch for the 1.1 stream 126 | 127 | `1.1.1+20200117.080221` 128 | 129 | 130 | #### appSemver vs version 131 | 132 | The `appSemver` portion of the CASE is the semver representation of the application in the CASE. The `version` portion of the CASE is the semver of the actual CASE itself. If the underlying installer (launch) technology changes in the CASE or metadata in the CASE changes, then the `version` field must change as well. The `appSemver` field for the CASE only changes when the version of the application underneath the CASE changes. 133 | 134 | #### appSemver vs appVersion 135 | 136 | The `appVersion` portion of the CASE is the marketing representation of the application. This version can be a semver compliant format, but it can be any string value that represents the customer facing version of the application. The `appSemver` portion of the CASE is mandated to be semver compliant format, for use in ordering and querying a CASE repository. 137 | 138 | #### additionalVersions example 139 | 140 | ```yaml 141 | additionalVersions: 142 | ibmCPDMinVersion: 143 | - semver: 1.0.0 144 | ibmCPLauncherVersions: 145 | - semver: 1.0.4 146 | - semver: 2.1.2 147 | ``` 148 | 149 | 150 | ### `supports` 151 | The supports CASE object defines various features that are supported by the CASE and product defined in the case. Specific details are described in the inventory items. 152 | 153 | The following support objects are available: 154 | 155 | #### `architectures` 156 | This describes the compute architectures supported by the CASE. Some specific values include: 157 | * `amd64`: 64-bit Intel/AMD x86 158 | * `ppc64le`: 64-bit little-endian PowerPC 159 | * `s390x`: Linux on IBM Z 160 | 161 | Example supporting all three architectures: 162 | ```yaml 163 | supports: 164 | architecture: 165 | amd64: {} 166 | ppc64le: {} 167 | s390x: {} 168 | ``` 169 | 170 | #### `k8sDistros` 171 | This describes the Kubernetes distributions that are supported by the CASE and product defined in the case. Some specific values include: 172 | 173 | * `icp`: IBM Cloud Private 174 | * `iks`: IBM Kubernetes Service 175 | * `rhocp3`: RedHat OpenShift Container Platform 3 176 | * `rhocp4`: RedHat OpenShift Container Platform 4 177 | * `mirrorByDigest`: `true` if the CASE supports image mirroring by digest, for example, using an ImageContentSourcePolicy (boolean) 178 | * `aks`: Microsoft Azure 179 | * `gce`: Google Compute Engine 180 | * `eks`: Amazon Enterprise Kubernetes Service 181 | 182 | Example supporting several Kubernetes distributions: 183 | ```yaml 184 | supports: 185 | k8sDistros: 186 | icp: {} 187 | iks: {} 188 | rhocp3: {} 189 | rhocp4: {} 190 | ``` 191 | 192 | 193 | #### `managedPlatforms` 194 | This describes the managed platforms supported by the CASE and product defined in the case. Managed platforms generally describe a vendor cloud and the supporting frameworks. Some specific values include: 195 | 196 | * `ibm`: The IBM Cloud 197 | * `amazon`: The Amazon cloud 198 | * `redhat`: The RedHat cloud 199 | * `google`: The Google cloud 200 | * `microsoft`: The Microsoft cloud 201 | 202 | Example supporting a few managed platforms: 203 | ```yaml 204 | supports: 205 | managedPlatforms: 206 | ibm: {} 207 | amazon: {} 208 | ``` 209 | -------------------------------------------------------------------------------- /110-roles.md: -------------------------------------------------------------------------------- 1 | # CASE roles.yaml Specification 2 | - [CASE roles.yaml Specification](#case-rolesyaml-specification) 3 | - [Status: Stable](#status-stable) 4 | - [Overview](#overview) 5 | - [Specification](#specification) 6 | 7 | ## Status: Stable 8 | 9 | ## Overview 10 | The `roles.yaml` includes metadata about the role an actor can play when running an Action on an Inventory Item. 11 | 12 | ## Specification 13 | The `roles.yaml` has the following attributes: 14 | 15 | * roles: The roles available to the CASE inventory item actions. 16 | * `metadata`: Desribes the roles. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 17 | * `roleDefs`: The role definition objects. 18 | * ``: A [CASE Property](010-case-structure.md#yaml-file-format) describing the role. (Required) 19 | * `metadata`: Describes the role. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 20 | 21 | -------------------------------------------------------------------------------- /120-prereqs.md: -------------------------------------------------------------------------------- 1 | # CASE prereqs.yaml Specification 2 | - [CASE prereqs.yaml Specification](#case-prereqsyaml-specification) 3 | - [Status: Stable](#status-stable) 4 | - [Overview](#overview) 5 | - [Specification](#specification) 6 | - [k8sResources](#k8sresources) 7 | - [k8sResourceVersions](#k8sresourceversions) 8 | - [k8sDistros](#k8sdistros) 9 | - [Distribution Resolvers](#distribution-resolvers) 10 | - [helm](#helm) 11 | - [client](#client) 12 | - [ibmCoreServices](#ibmcoreservices) 13 | - [Specifying Prerequisite Version Ranges](#specifying-prerequisite-version-ranges) 14 | - [Non-functional versions](#non-functional-versions) 15 | 16 | ## Status: Stable 17 | 18 | ## Overview 19 | The `prereqs.yaml` file describes any pre-requisites that the the CASE may require of a target cluster. This specification uses the concept of Resolver to return a boolean result from the body of the object. The resolver can then be referenced by the inventory item [Action rules](220-actions.md#prereq-rules) to construct expressions. 20 | 21 | ## Specification 22 | The `prereqs.yaml` has the following attributes: 23 | 24 | * `prereqs`: The roles available to the CASE inventory item actions. 25 | * `metadata`: General metadata about the prereqs. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 26 | * `prereqDefs`: The prereq resolvers. 27 | * `k8sResources`: The resolver for Kubernetes resources. See [k8sResources](#k8sResources). 28 | * `k8sResourceVersions`: The resolver for Kubernetes resource API versions. See [k8sResourceVersions](#k8sResourceVersions). 29 | * `k8sDistros`: The resolver for Kubernetes distribution vendor and version. See [k8sDistros](#k8sDistros). 30 | * `helm`: The resolver for Helm versions. See [helm](#helm). 31 | * `client`: The client-side program requirements. See [client](#client). 32 | * `ibmCoreServices` The resolver for IBM core services. See [ibmCoreServices](#ibmCoreServices). 33 | 34 | ### k8sResources 35 | This resolver is used to identify specific instances of resources in the target Kubernetes cluster. 36 | 37 | The `k8sResources` resource is a set of objects each with the following attributes: 38 | * ``: A [CASE Property](010-case-structure.md#yaml-file-format) describing the resource. (Required) 39 | * `metadata`: Describes the resource. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 40 | * `kind`: The kind of resource to resolve. 41 | * `apiGroup`: The API Group of the resource. 42 | * `version`: The version of the resource API. 43 | * `name`: The name of the resource (required if not specifying a `selector` or `fieldSelector`) 44 | * `selector`: The label selector (optional) 45 | * `matchExpressions`: The label match expression map. See the [Kubernetes matchExpressions documentation](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#resources-that-support-set-based-requirements). 46 | * `fieldSelector`: The field selector chain (optional) 47 | * `matchExpressions`: The field match expression chain. SEe the [Kubernetes field-selectors documentation](https://kubernetes.io/docs/concepts/overview/working-with-objects/field-selectors/). 48 | 49 | 50 | ### k8sResourceVersions 51 | This resolver is used to identify specific resource kinds and versions in the target Kubernetes cluster. 52 | 53 | The `k8sResourceVersions` resource is an array of objects each with the following attributes: 54 | * ``: A [CASE Property](010-case-structure.md#yaml-file-format) describing the resource type. (Required) 55 | * `metadata`: Describes the resource version. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 56 | * `kind`: The kind of resource to resolve. 57 | * `apiGroup`: The API Group of the resource. 58 | * `version`: The version of the resource API. 59 | 60 | 61 | 62 | ### k8sDistros 63 | This resolver is used to identify the vendor and version of the target Kubernetes cluster. Each Distribution Resolver includes distribution-unique rules for determining the vendor of the distribution. If the vendor is not required, use the `kubernetes` resolver. 64 | 65 | The `k8sDistros` resource is an set objects each with the following attributes: 66 | * ``: One of a set of pre-defined kubernetes distribution resolvers 67 | * `metadata`: Describes the distro. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 68 | * `semver`: The semantic version constraint of the Kubernetes distribution (optional). See [semver version constraints](#semver-version-constraints). 69 | 70 | #### Distribution Resolvers 71 | Each Kubernetes distribution resolver is a well known name which include: 72 | 73 | * `kubernetes` - This is the default resolver when no other distribution can be resolved. 74 | * `ibmCloud` - IBM Cloud Kubernetes Service 75 | * `ibmCloudPrivate` - IBM Cloud Private 76 | * `openshift` - Red Hat OpenShift Container Platform 77 | * `googleGKE` - Google Kubernetes Engine 78 | * `azureAKS` - Azure Kubernetes Service 79 | * `amazonEKS` - Amazon Elastic Container Service for Kubernetes 80 | 81 | ### helm 82 | This resolver is used to identify the version of Helm and/or Tiller. If this resolver is present, then a Helm client must be configured and available. 83 | 84 | The `helm` resource has the following attributes: 85 | * ``: A [CASE Property](010-case-structure.md#yaml-file-format) describing the Helm prerequisite. (Required) 86 | * `metadata`: Describes the Helm prerequisite. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 87 | * `helmVersion`: The semantic version constraint of the Helm client (optional). See [semver version constraints](#semver-version-constraints). 88 | * `tillerVersion`:The semantic version constraint of Tiller (optional). See [semver version constraints](#semver-version-constraints). 89 | 90 | 91 | ### client 92 | This resolver is used to identify client-side environment requirements needed to run an inventory action. 93 | 94 | The `client` resource has the following attributes: 95 | * ``: A [CASE Property](010-case-structure.md#yaml-file-format) describing the client prerequisite. (Required) 96 | * `metadata` Describes the client prerequisite. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 97 | * `command`: The command name expected to be in the system path of the operating system. (Required) 98 | * `versionArgs`: The command line arguments needed to retrieve the version of the command. For example, the `versionArgs` parameter for `go version` would be `version`. Default: `--version`. 99 | * `versionRegex`: The regex to match against the output of the command to verify the expected version is installed. If not specified, any version of the command found in the system path is considered appropriate. 100 | 101 | **Note:** The following reserved characters are not allowed in the `command` or `versionArgs` properties: `|` `;` `&` `$` `>` `<` `\` `!` `` ` `` 102 | 103 | 104 | ### ibmCoreServices 105 | This resolver is used to identify the availability of IBM core services in the target Kubernetes cluster. IBM core services are available with IBM Cloud Paks. 106 | 107 | Each IBM core service resolver key is a well known service name. The value specified here is typically the primary service of a feature that an IBM Cloud Pak or IBM certified container utilizes directly. 108 | 109 | For a detailed list of services available IBM Cloud Private Knowledge Center. 110 | 111 | Some common components include: 112 | 113 | * `auth-idp`: The IBM Cloud Private Identity and Access Management service. 114 | * `cert-manager`: The component that manages the lifecycle of certificates 115 | * `logging`: The suite of logging services, including ElasticSearch and Kibana. 116 | * `monitoring`: The suite of monitoring services, including Prometheus and Grafana. 117 | * `nginx-ingress`: The default Ingress that's used on the ICP Proxy nodes. 118 | * `service-catalog`: Implements the Open Service Broker API to provide service broker integration. 119 | * `storage-gluster-fs`: The Gluster filesystem. 120 | 121 | Each service-resolver includes the following fields: 122 | 123 | * `` - Reserved for future use, such as versioning. 124 | 125 | 126 | ## Specifying Prerequisite Version Ranges 127 | A `Range` is a set of conditions that specify which versions satisfy the prerequisite. This specification utilizes basic comparisons and standard AND/OR logic to define the expected version range. 128 | 129 | The basic comparisons are: 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 |
=equal
!=not equal
>greater than
<less than
>=greater than or equal
<=less than or equal
157 | 158 | Basic comparisons are combined into logical AND and OR combinations. ANDs are specified with spaces between comparison objects and ORs are specified with the standard double-pipe character: `||`. Logical AND is given higher priority than OR and parenthesis are not supported. 159 | 160 | Examples: 161 | * This example will support any v1.x version above or equal to 1.11.3: 162 | * `>=1.11.3 <2` 163 | * This example will support either versions 1.x through 2.x or versions 3.4.0 and above 164 | * `>= 1.0 <3.0.0 || >= 3.4.0` 165 | * To support any version other than 2.11.2: 166 | * `<2.11.2 || >2.11.2` or, more simply: 167 | * `!=2.11.2` 168 | 169 | ### Non-functional versions 170 | 171 | As stated in the [case.yaml specification](100-case.md#version), CASE supports non-functional versions. These are specified after the standard version and are prefixed with a plus sign (`+`). In order of preference, non-functional versions come after a standard release. For example, `1.0.0 < 1.0.0+20191008.162055`. 172 | -------------------------------------------------------------------------------- /130-certification.md: -------------------------------------------------------------------------------- 1 | # CASE certification.yaml Specification 2 | - [CASE certification.yaml Specification](#case-certificationyaml-specification) 3 | - [Status: Stable](#status-stable) 4 | - [Overview](#overview) 5 | - [Specification](#specification) 6 | - [Specifying certification type in case.yaml](#specifying-certification-type-in-caseyaml) 7 | - [Examples](#examples) 8 | - [IBM certified container example](#ibm-certified-container-example) 9 | - [IBM certified Cloud Pak example w/ exception](#ibm-certified-cloud-pak-example-w-exception) 10 | - [IBM certified minimum catalog example](#ibm-certified-minimum-catalog-example) 11 | - [IBM certified container with security report example](#ibm-certified-container-with-security-report-example) 12 | - [Example case.yaml certifications section for an ibmccp license](#example-caseyaml-certifications-section-for-an-ibmccp-license) 13 | 14 | 15 | ## Status: Stable 16 | 17 | ## Overview 18 | This specification supports multiple certifications. Certifications are stored in the `certifications` directory in the CASE. Certifications are added to the case when a certification is completed. 19 | 20 | ## Specification 21 | Each certification file must be named as follows: `.yaml` 22 | 23 | Where the `provider` is the provider of the certification and the `type` is some value that describes the certification. 24 | 25 | The certification name must a total of 50 characters or less. 26 | The `provider` MUST: 27 | * begin with a lower case character 28 | * contain alpha-numeric characters or the following special characters: `_` 29 | 30 | The `type` MUST: 31 | * begin with a lower case character 32 | * contain alpha-numeric characters or the following special characters: `_-` 33 | 34 | 35 | * `certification`: The certification object (required) 36 | * `metadata`: Describes the certification. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 37 | * `id`: Unique string identifier assigned during certification (required) 38 | * `provider`: The certification provider identifier. A provider must be unique by vendor or certification authority. For example: `ibm`. See above for naming requirements. (required) 39 | * `type`: The certification type unique to the certification provider. See above for naming requirements. (required) 40 | * `issueDate`: The date in the format MM/DD/YYYY which the certification was issued (required) 41 | * `expirationDate`: The date in the format MM/DD/YYYY which the certification expires (required) 42 | * `terms` : The terms description (required) 43 | * `exceptions` : An array of exception(s) granted during certification (optional) 44 | * `id`: Unique string identifier for exception assigned during certification (required) 45 | * `description`: The description of the exception for documentation (required) 46 | * `remediation`: Planned remediation of the exception for documentation (required) 47 | * `resources`: The resources object for any additional certification-related files. 48 | * `metadata`: Information about the resources. 49 | * `resourceDefs`: The resource resolvers. 50 | * `files`: Array of file object references that are embedded in this CASE inventory item. 51 | * `metadata`: Metadata about the file reference. 52 | * `ref`: The relative path to the `files` directory. 53 | * `mediaType`: The media type of the file as supported by this spec. See [Media Types](#Media-Types). 54 | 55 | __Defaults__ : 56 | - terms : "Valid from date of issue. Security vulnerability management and enhancements are delivered on the latest version of the chart and images", but may be overriden at certification if alternate terms approved. 57 | 58 | ## Specifying certification type in case.yaml 59 | 60 | `case.yaml` contains a `certifications` object which should contain a list of certifications for the CASE. The values in this section should match the certification file names in your `certifications/` directory. 61 | 62 | # Examples 63 | 64 | ## IBM certified container example 65 | ```yaml 66 | certification: 67 | metadata: 68 | name: "ibmccs" 69 | displayName: "IBM certified container software" 70 | id: "75b05dfb-8988-4caa-8a6c-36f8ae5fe211" 71 | issueDate: "08/01/2019" 72 | expirationDate: "07/30/2020" 73 | terms: "Valid from date of issue. Security vulnerability management and enhancements are delivered on the latest version of the chart and images" 74 | ``` 75 | 76 | ## IBM certified Cloud Pak example w/ exception 77 | ```yaml 78 | certification: 79 | metadata: 80 | name: "ibmccp" 81 | displayName: "IBM Certified Cloud Pak" 82 | id: "85b05dfb-8988-5caa-9a6c-36f8ae5fe212" 83 | issueDate: "10/01/2019" 84 | expirationDate: "03/31/2020" 85 | terms: "Valid from date of issue. Security vulnerability management and enhancements are delivered on the latest version of the chart and images" 86 | exceptions: 87 | - id: "12345" 88 | description: "Non RedHat certificated operator : UBI image unavailable for community operator, verified manual per standards and supported by IBM" 89 | remediation: "Contribute UBI based image to community operator and RedHat Certify with next release" 90 | ``` 91 | 92 | ## IBM certified minimum catalog example 93 | ```yaml 94 | certification: 95 | metadata: 96 | name: "ibmmc" 97 | displayName: "IBM minimum catalog" 98 | id: "99b05dfb-8900-4caa-8a8c-36f8ae5fe333" 99 | issueDate: "01/01/2019" 100 | expirationDate: "12/31/2019", 101 | terms: "Valid from date of issue. Security vulnerability management and enhancements are delivered on the latest version of the chart and images" 102 | ``` 103 | 104 | ## IBM certified container with security report example 105 | ```yaml 106 | certification: 107 | metadata: 108 | name: "ibmccs" 109 | displayName: "IBM certified container software" 110 | id: "75b05dfb-8988-4caa-8a6c-36f8ae5fe211" 111 | issueDate: "08/01/2019" 112 | expirationDate: "07/30/2020" 113 | terms: "Valid from date of issue. Security vulnerability management and enhancements are delivered on the latest version of the chart and images" 114 | resources: 115 | metadata: 116 | name: certReport 117 | displayName: certReport 118 | displayDescription: certification security report 119 | resourceDefs: 120 | files: 121 | - ref: ExternalSecurity.pdf 122 | mediaType: application/pdf 123 | ``` 124 | 125 | ## Example case.yaml certifications section for an ibmccp license 126 | ```yaml 127 | certifications: 128 | ibmccp: {} 129 | ``` 130 | -------------------------------------------------------------------------------- /140-resource-groups.md: -------------------------------------------------------------------------------- 1 | # CASE case.yaml Specification 2 | - [CASE case.yaml Specification](#case-caseyaml-specification) 3 | - [Status: Stable](#status-stable) 4 | - [Overview](#overview) 5 | - [Specification](#specification) 6 | - [Description](#description) 7 | - [Example](#example) 8 | 9 | ## Status: Stable 10 | 11 | ## Overview 12 | The `resourceGroups.yaml` file contains a collection of groups defined elsewhere in the CASE and is provided for the simplification of handling these groups. Currently, only image groups exist in the CASE specification and are defined in the [CASE resources.yaml specification](210-resources.md). `resourceGroups.yaml` defines a collection of groups and provides the ability to define product components and configurations. 13 | 14 | ## Specification 15 | * `resourceGroups`: The resourceGroups object (required) 16 | * `resourceGroupsDefs`: The resource group 17 | * ``: A [CASE Property](100-case.md##YAML-File-Format) defining the resource group. For example: `trial` (required) 18 | * `metadata`: Describes the resource group. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details on metadata 19 | * `default`: A boolean metadata parameter. If set to true, designates that this is the default image group for the CASE. Only one resource group may be designated as the default for a CASE. 20 | * `groups`: A list of groups that make up this resource group (required) 21 | * `name`: The group name (required) 22 | 23 | ### Description 24 | 25 | A CASE can define one or more groups within the `resources.yaml` files in each of the CASE's inventory items (see [Container Image Groups](210-resources.md#container-image-groups)). These groups provide a granular way to create components or configurations within a CASE without needing to create separate CASEs for each component or configuration. `resourceGroups.yaml` provides an additional layer to allow for combining multiple groups into a single definition for easier consumption. 26 | 27 | ### Example 28 | 29 | The following example shows a `resourceGroups.yaml` defining two groups, `demo` and `prod`, and sets the demo group to be the default group for the CASE: 30 | 31 | ``` 32 | resourceGroups: 33 | resourceGroupsDefs: 34 | demo: 35 | metadata: 36 | default: true 37 | groups: 38 | - name: "demoImages" 39 | - name: "coreComponents" 40 | prod: 41 | groups: 42 | - name: "prodImages" 43 | - name: "coreComponents" 44 | - name: "prodDatabase" 45 | ``` -------------------------------------------------------------------------------- /200-inventory.md: -------------------------------------------------------------------------------- 1 | # CASE inventory Specification 2 | - [CASE inventory Specification](#case-inventory-specification) 3 | - [Status: Stable](#status-stable) 4 | - [Overview](#overview) 5 | - [`inventory` directory specification.](#inventory-directory-specification) 6 | - [Inventory item directory specification](#inventory-item-directory-specification) 7 | - [`inventory.yaml` Specification](#inventoryyaml-specification) 8 | 9 | ## Status: Stable 10 | 11 | ## Overview 12 | The inventory directory is a collection of inventory items. Each of the inventory items are included as required or optional entities of the CASE. 13 | 14 | ## `inventory` directory specification. 15 | The inventory directory contains sub-directories that represent Inventory Items. Each inventory item directory is a path navigable name of the inventory item within the CASE specification. 16 | * The `inventory` directory includes NO FILES. It ONLY includes sub-directories that contain metadata about inventory items. 17 | * The inventory item sub-directory name MUST follow the property name conventions defined in the [CASE YAML Specification](010-case-structure.md#YAML-File-Format) 18 | 19 | Example file structure: 20 | ``` 21 | my-case/ 22 | ... 23 | inventory/ 24 | clusterSetup/ # Inventory Item 25 | actions.yaml 26 | inventory.yaml 27 | README.md 28 | resources.yaml 29 | files/ # Optional resources 30 | myApplication/ # Inventory Item 31 | actions.yaml 32 | inventory.yaml 33 | README.md 34 | resources.yaml 35 | files/ # Optional resources 36 | ``` 37 | 38 | ## Inventory item directory specification 39 | Each inventory item directory MUST include the following files: 40 | - [inventory.yaml](#inventoryyaml-Specification) 41 | - README.md 42 | 43 | Each inventory item directory MAY include the following files: 44 | - [actions.yaml](220-actions.md) 45 | - [resources.yaml](210-resources.md) 46 | 47 | Each inventory item MAY include an optional `files` folder which includes any embedded resources that should be included the case. See [resources.yaml](210-resources.md) for details. 48 | 49 | ## `inventory.yaml` Specification 50 | The inventory item name MUST follow the [CASE property specification](010-case-structure.md#yaml-file-format). 51 | 52 | The `inventory.yaml` has the following attributes: 53 | * `inventory`: The resources object. (required) 54 | * `metadata`: Information about the resources. 55 | * `k8sScope`: The Kubernetes scope this inventory item applies to. For example: `cluster` or `namespace` 56 | 57 | -------------------------------------------------------------------------------- /220-actions.md: -------------------------------------------------------------------------------- 1 | # CASE actions.yaml Specification 2 | - [CASE actions.yaml Specification](#case-actionsyaml-specification) 3 | - [Status: Stable](#status-stable) 4 | - [Overview](#overview) 5 | - [Specification](#specification) 6 | - [Prereq Rules](#prereq-rules) 7 | - [Kubernetes Permission Rule Example](#kubernetes-permission-rule-example) 8 | 9 | ## Status: Stable 10 | 11 | 12 | ## Overview 13 | The `actions.yaml` includes the actions that can be applied to the inventory item and the prerequisites that are required to perform the action, including the permissions required of the current user. 14 | 15 | ## Specification 16 | * `actions`: The actions object (required) 17 | * `metadata`: Information about the actions described in this file 18 | * `actionDefs`: The actions. 19 | * ``: A [CASE Property](100-case.md##YAML-File-Format) defining the action. For example: `install` (required) 20 | * `metadata`: Describing the action. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 21 | * `roles`: One or roles required to perform this action. See [CASE Roles](110-roles.md) for details (required) 22 | * `requires`: A logical expression of [CASE Prereq Resolver](120-prereqs.md) JSON Pointers that describe the prerequistes which are REQUIRED in order to install this inventory item (optional) 23 | * [<Prereq Expression>](#Prereq-Rules) The prerequisite logical expression. 24 | * `k8sPermissions`: Kubernetes RBAC permissions required to perform this action as the current user on the target cluster (optional). 25 | * `rules`: An array of conditional Kubernetes RBAC Rules 26 | * `ifExpression`: A logical expression of [CASE Prereq Resolver](120-prereqs.md) JSON Pointers that must evaluate to `true` to consider the permission (optional) 27 | * `rule`: A Kubernetes RBAC rule. See the [Kubernetes SelfSubjectAccessReviewSpec API for details](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#resourceattributes-v1-authorization-k8s-io) 28 | * `group`: The API Group of the Resource. "*" means all. (required) 29 | * `name`: The name of the resource being requested for a "get" or deleted for a "delete". "" (empty) means all. (optional) 30 | * `namespace`: The namespace of the action being requested. (Optional, default=all) 31 | * `resource`: One of the existing resource types. "*" means all. (required) 32 | * `subresource`: One of the existing resource types. "" means none. (optional) 33 | * `verbs`: A list of kubernetes resource API verbs, for example: get, list, watch, create, update, delete, proxy. "*" means all. (required) 34 | * `version`: The API Version of the Resource. Absence or "*" means all. (optional) 35 | 36 | ## Prereq Rules 37 | Prerequisite resolvers can be referenced as logical expressions using a subset of the [JSONLogic specification](http://jsonlogic.com/) and [JSON Pointers](https://tools.ietf.org/html/rfc6901). Only logical expressions are supported. 38 | 39 | Example: 40 | ``` 41 | actions: 42 | actionDefs: 43 | install: 44 | ... 45 | requires: 46 | and: 47 | - or: 48 | - "/case/prereqs/k8sDistros/ibmCloud" 49 | - "/case/prereqs/k8sDistros/openshift" 50 | - or: 51 | - and: 52 | - "!": 53 | - "/case/prereqs/k8sDistros/openshift" 54 | - or: 55 | - "/case/prereqs/k8sResources/ibmRestrictedPSP" 56 | - "/case/prereqs/k8sResources/etcdControllerPSP" 57 | - and: 58 | - "/case/prereqs/k8sDistros/openshift" 59 | - or: 60 | - "/case/prereqs/k8sResources/ibmRestrictedSCC" 61 | - "/case/prereqs/k8sResources/etcdControllerSCC" 62 | ``` 63 | 64 | This translates to: 65 | 66 | * Install if: 67 | * Either the Kubernetes distribution is ibmCloud or openshift 68 | * AND 69 | * if openshift, then either the ibmRestrictedSCC or etcdControllerSCC resources must be installed. 70 | * if not openshift, then either the ibmRestrictedPSP or etcdControllerPSP resources must be installed. 71 | 72 | ## Kubernetes Permission Rule Example 73 | 74 | Example Rule: 75 | ``` 76 | actions: 77 | actionDefs: 78 | install: 79 | ... 80 | k8sPermissions: 81 | rules: 82 | - ifExpression 83 | - "!": 84 | - "/case/prereqs/k8sDistros/openshift" 85 | apiGroups: 86 | - extensions 87 | resources: 88 | - podsecuritypolicies 89 | verbs: 90 | - get 91 | - list 92 | - watch 93 | - create 94 | - patch 95 | - update 96 | version: '*' 97 | 98 | - ifExpression: 99 | "/case/prereqs/k8sDistros/openshift" 100 | apiGroups: 101 | - security.openshift.io 102 | resources: 103 | - securitycontextconstraints 104 | verbs: 105 | - get 106 | - list 107 | - watch 108 | - create 109 | - patch 110 | - update 111 | ``` 112 | 113 | This translates to: 114 | 115 | * Check Permissions: 116 | * The Kubernetes distribution is NOT openshift: 117 | * Check permissions for the specified verbs for the podsecuritypolicies resource in the extensions API Group. 118 | * `kubectl auth can-i get podsecuritypolicies.extensions` 119 | * `kubectl auth can-i list podsecuritypolicies.extensions` 120 | * `kubectl auth can-i watch podsecuritypolicies.extensions` 121 | * `kubectl auth can-i create podsecuritypolicies.extensions` 122 | * `kubectl auth can-i patch podsecuritypolicies.extensions` 123 | * `kubectl auth can-i update podsecuritypolicies.extensions` 124 | * The Kubernetes distribution IS openshift: 125 | * Check permissions for the specified verbs for the securitycontextconstraints resource in the security.openshift.io API Group. 126 | * `kubectl auth can-i get securitycontextconstraints.security.openshift.io` 127 | * `kubectl auth can-i list securitycontextconstraints.security.openshift.io` 128 | * `kubectl auth can-i watch securitycontextconstraints.security.openshift.io` 129 | * `kubectl auth can-i create securitycontextconstraints.security.openshift.io` 130 | * `kubectl auth can-i patch securitycontextconstraints.security.openshift.io` 131 | * `kubectl auth can-i update securitycontextconstraints.security.openshift.io` 132 | 133 | -------------------------------------------------------------------------------- /300-signature.md: -------------------------------------------------------------------------------- 1 | # CASE signature.yaml Specification 2 | 3 | - [CASE signature.yaml Specification](#case-signatureyaml-specification) 4 | - [Status: Stable](#status-stable) 5 | - [Overview](#overview) 6 | - [Specification](#specification) 7 | - [What needs to be Signed](#what-needs-to-be-signed) 8 | - [How can we Avoid Hash Problems?](#how-can-we-avoid-hash-problems) 9 | - [Workflow for Signing the CASE](#workflow-for-signing-the-case) 10 | - [Signature Validation](#signature-validation) 11 | 12 | ## Status: Stable 13 | 14 | ## Overview 15 | 16 | Our digital signature strategy is an adaptation of the [JWT](https://jwt.io/introduction/) method of signing a payload. The signature provides a way to validate that the CASE downloaded is the CASE that was certified. There are four parts to the signature: the header, the data, the x509Certificate, and the signature. 17 | 18 | ## Specification 19 | 20 | The `signature.yaml` has the following attributes: 21 | 22 | * `headers`: Signature header. (Required) 23 | * `alg`: The algorithm used to encrypt the signature. (Required) 24 | * `version`: The version of the CASE specification. (Required) 25 | * `data`: The information to be verified upon delivery. (Required) 26 | * `digest`: A SHA-256 digest of the canonical JSON version of the CASE. (Required) 27 | * `x509Certificates`: An array of certificates used for decrypting the signature. (Required) 28 | * `chain`: The certificate chain. (Required) 29 | * `certificate`: The base64 encoded certificate. (Required) 30 | * `signature`: The digital signature. (Required) 31 | 32 | ### What needs to be Signed 33 | All JSON files included in this specification's canonical JSON will be signed. Any additional non-YAML files (resource files, licenses, readmes) are included via their digest found in digests.yaml. 34 | 35 | For example: 36 | ``` 37 | my-case/ 38 | case.yaml 39 | prereqs.yaml 40 | qualification.yaml 41 | certification.yaml 42 | digests.yaml 43 | README.md 44 | roles.yaml 45 | inventory/ 46 | / 47 | inventory.yaml 48 | actions.yaml 49 | README.md 50 | resources.yaml 51 | files/ 52 | 53 | signature.yaml 54 | ``` 55 | 56 | In the above example, all yaml files will included in the signature via the canonical JSON file while the README.md files and the items in the files directory will be included indirectly via their entry in digests.yaml. 57 | 58 | ### How can we Avoid Hash Problems? 59 | 60 | In order to avoid hashing problems there needs to be a canonical form for the data. The format chosen is canonical JSON. YAML files are converted into a single canonical JSON file and then that file is hashed to produce the signature. 61 | 62 | ### Workflow for Signing the CASE 63 | 64 | ![CASE signing flow diagram](./design/case-signature-flow-diagram.png) 65 | 66 | Steps involved: 67 | 68 | 1. Concatonate all YAML files into a single file. 69 | 2. Convert this file to be a canonical JSON form file. 70 | 3. Create a digest of the canonical using SHA-256 encoding. 71 | 4. Add this digest to the data property of `signature.yaml`. 72 | 5. Create a hashsum of the headers, digest, expiration date, and x509 certificates. This is the signature. 73 | 6. Add this signature to `signature.yaml`. 74 | 75 | ### Signature Validation 76 | 77 | We will use the PKI method for validating the signature. This means that a Public / Private key is needed to sign the CASE digest. 78 | 79 | The receiver installs the CASE and verifies the digital signature. This is done by using the public key to decrypt the digital signature (giving the original digest of the content). The content in the CASE is then hashed using SHA-256, and the resulting values are compared. If they are a match then the content the reciever has is the same as the content the server sent. The public key is read by the receiver through the signature.yaml file in the x509Certificate section. 80 | -------------------------------------------------------------------------------- /310-digests.md: -------------------------------------------------------------------------------- 1 | # CASE digests.yaml Specification 2 | - [CASE digests.yaml Specification](#case-digestsyaml-specification) 3 | - [Status: Stable](#status-stable) 4 | - [Overview](#overview) 5 | - [Specification](#specification) 6 | - [Resource Digests](#resource-digests) 7 | 8 | ## Status: Stable 9 | 10 | ## Overview 11 | The `digests.yaml` includes digests (cryptographic hashes) of select artifacts within the CASE specification. Specifically, the artifacts that are not part of the canonical JSON representation of the CASE. This includes: 12 | 1. License files 13 | 2. Inventory Resource Files 14 | 3. Inventory Resource References 15 | 16 | ## Specification 17 | The `digests.yaml` has the following attributes: 18 | * `digests`: The digests available to the CASE inventory item actions. 19 | * `metadata`: Describes the digests. See [CASE Metadata](010-case-structure.md#Specification-metadata-and-versioning) for details. 20 | * `digestDefs`: The role definition objects. 21 | * `readme`: The digest of the CASE `README.md` file. 22 | * `digest`: The digest for the README. 23 | * `size`: The README size. 24 | * `skip`: If true, skip this entry when evaluating the digest. 25 | * `inventory`: The inventory items. 26 | * ``: The name of the inventory item. 27 | * `readme`: The readme.md file. 28 | * `digest`: The digest for the README. 29 | * `size`: The README size. 30 | * `skip`: If true, skip this entry when evaluating the digest. 31 | * `resources`: A list of resources 32 | * `resourceDefs`: The resource resolvers. 33 | * `cases`: Array of digest objects for referenced cases 34 | * `digest`: A CASE archive digest. 35 | * `size`: The CASE archive size. 36 | * `skip`: If true, skip this entry when evaluating the digest. 37 | * `files`: Array of digest objects for referenced files. 38 | * `digest`: Array of digest strings. 39 | * `size`: The file size. 40 | * `skip`: If true, skip this entry when evaluating the digest. 41 | * `helmCharts`: Array of digest objects for referenced Helm charts 42 | * `digest`: Array of digest strings. 43 | * `size`: The Helm Archive size. 44 | * `skip`: If true, skip this entry when evaluating the digest. 45 | * `containerImages`: Array of digest objects for referenced container images 46 | * `digest`: Array of digest strings. 47 | * `skip`: If true, skip this entry when evaluating the digest. 48 | * `licenses`: The main license. 49 | * `digest`: The digest of the license file. 50 | * `size`: The file size. 51 | * `skip`: If true, skip this entry when evaluating the digest. 52 | * `case`: The non-file elements of the CASE. 53 | * `digest`: The digest of the canonical representation of the case. 54 | * `size`: The size of the canonical representation of the case. 55 | * `skip`: If true, skip this entry when evaluating the digest. 56 | * `licenses`: The licenses. 57 | * ``: The key of the license item. 58 | * `digest`: The digest of the license file. 59 | * `size`: The file size. 60 | * `skip`: If true, skip this entry when evaluating the digest. 61 | 62 | 63 | ### Resource Digests 64 | Each resource digest is in the following format described in the [OCI Digest](https://github.com/opencontainers/image-spec/blob/master/descriptor.md#digests) specification: 65 | 66 | ``` 67 | digest ::= algorithm ":" encoded 68 | algorithm ::= algorithm-component (algorithm-separator algorithm-component)* 69 | algorithm-component ::= [a-z0-9]+ 70 | algorithm-separator ::= [+._-] 71 | encoded ::= [a-zA-Z0-9=_-]+ 72 | ``` 73 | 74 | Supported algorithms include: 75 | * `sha256`: a collision-resistant hash function, chosen for ubiquity, reasonable size and secure characteristics. Implementations MUST implement SHA-256 digest verification for use in descriptors. The encoded portion MUST match /[a-f0-9]{64}/. Note that [A-F] MUST NOT be used here. 76 | -------------------------------------------------------------------------------- /400-archive.md: -------------------------------------------------------------------------------- 1 | # CASE Archive Specification 2 | - [CASE Archive Specification](#case-archive-specification) 3 | - [Status: Stable](#status-stable) 4 | - [Overview](#overview) 5 | - [Specification](#specification) 6 | - [Archive Name](#archive-name) 7 | - [Archive contents](#archive-contents) 8 | 9 | ## Status: Stable 10 | 11 | ## Overview 12 | A CASE Archive is TGZ (GZipped Tarball) of the files in the CASE directory structure. 13 | 14 | ## Specification 15 | 16 | ### Archive Name 17 | The archive name must match the name of the case: 18 | ``` 19 | Archive Name = CASE Name "-" Version ".tgz" 20 | Version = The case.version 21 | CASE Name = The case.name / CASE directory name 22 | ``` 23 | 24 | ### Archive contents 25 | The root directory of the archive must be the CASE folder. 26 | 27 | Example, to create a CASE archive of the `mydatabase` CASE, version 1.0.0+20191113.1530.cve2019-1234 (with a consistent hash): 28 | ``` 29 | > cd /tmp/mycases 30 | > ls -1 31 | myapp 32 | mydatabase 33 | > tar -cf - mydatabase/ | gzip -nc > mydatabase-1.0.0+20191113.1530.cve2019-1234.tgz 34 | > ls -1 35 | myapp 36 | mydatabase 37 | mydatabase-1.0.0+20191113.1530cve2019-1234.tgz 38 | ``` 39 | 40 | See the [createArchive.sh](utilities/createArchive.sh) for an example on how a CASE archive can be built with the correct directory format and a consistent digest/hash. 41 | -------------------------------------------------------------------------------- /500-repository.md: -------------------------------------------------------------------------------- 1 | # CASE Repository Specification 2 | 3 | - [CASE Repository Specification](#case-repository-specification) 4 | - [Status: Stable](#status-stable) 5 | - [Overview](#overview) 6 | - [Specification](#specification) 7 | - [Files and Folders](#files-and-folders) 8 | - [Descriptors](#descriptors) 9 | - [Repository base index descriptor](#repository-base-index-descriptor) 10 | - [CASE product index descriptor](#case-product-index-descriptor) 11 | - [CASE product version descriptor](#case-product-version-descriptor) 12 | - [Semver and Semver Comparison Formats](#semver-and-semver-comparison-formats) 13 | - [Non-functional CASE versions](#non-functional-case-versions) 14 | 15 | ## Status: Stable 16 | 17 | ## Overview 18 | The CASE repository is a location where CASE packages can be stored and shared. The folder and file names are well-defined such that traversing through the repository can be done without querying the contents of a directory. 19 | 20 | ## Specification 21 | A CASE repository is made up of three levels of directories, each containing a descriptor file for that level. 22 | 23 | ## Files and Folders 24 | 25 | The files described here are well named unless included in ``, in which a name is based on the CASE name or version. 26 | 27 | ``` 28 | index.yaml # A file containing a list of all CASEs in this repository 29 | / # A folder containing one or more versions of a CASE 30 | index.yaml # A file containing information about the CASE and a list of the versions available in the repository 31 | / # A folder containing a specific version of a CASE 32 | version.yaml # A file describing the version of the CASE in this directory 33 | -.tgz # The CASE tgz file 34 | ``` 35 | 36 | ### Descriptors 37 | 38 | Each directory in the CASE repository contains a descriptor file with information about the contents of the directory. The descriptor at the repository base directory and at the CASE directory is named `index.yaml` while the descriptor for a specific version of a CASE is named `version.yaml`. 39 | 40 | #### Repository base index descriptor 41 | 42 | The repository base index provides a list of all of the CASEs hosted in the repository and includes the latest version and associated application version. 43 | 44 | * `apiVersion`: The CASE repository index API version. (Required) 45 | * `entries`: A list of CASEs that are in this CASE repository. (Required) 46 | * ``: The name of the CASE 47 | * `latestVersion`: The latest version of the CASE in the repository (Required) 48 | * `latestAppVersion`: The latest application version of this CASE in the repository (Required) 49 | * `latestAppSemver`: The latest semver representation of the application of this CASE in the repository 50 | 51 | Example: 52 | 53 | ``` 54 | apiVersion: v1 55 | entries: 56 | etcd-operator-case: 57 | latestVersion: 1.0.0 58 | latestAppVersion: 3.0.0 59 | redis-case: 60 | latestVersion: 1.2.1 61 | latestAppVersion: 5.0.0 62 | latestAppSemver: 5.0.0 63 | ``` 64 | 65 | #### CASE product index descriptor 66 | 67 | The CASE product index provides additional information about the product including a list of versions and associated app versions available in the CASE repository. 68 | 69 | * `apiVersion`: The CASE repository index API version. (Required) 70 | * `latestVersion`: The latest version of the CASE in the repository (Required) 71 | * `latestAppVersion`: The latest application version of this CASE in the repository (Required) 72 | * `latestAppSemver`: The latest semver representation of the application of this CASE in the repository 73 | * `versions`: A list of versions of the CASE available in the repository (Required) 74 | * ``: The CASE version 75 | * `appVersion`: The application version associated with this version of the CASE (Required) 76 | * `appSemver`: The semver application version associated with this version of the CASE 77 | 78 | Example: 79 | 80 | ``` 81 | apiVersion: v1 82 | latestVersion: "1.0.0" 83 | latestAppVersion: "3.0.0" 84 | latestAppSemver: "3.0.0" 85 | versions: 86 | 0.9.0: 87 | appVersion: "2.0.0" 88 | appSemver: "2.0.0" 89 | 1.0.0: 90 | appVersion: "3.0.0" 91 | appSemver: "3.0.0" 92 | ``` 93 | 94 | #### CASE product version descriptor 95 | 96 | The CASE version descriptor provides information about the specified version of the product. 97 | 98 | * `specVersion`: The CASE spec version this CASE is written against. (Required) 99 | * `created`: The date this CASE was created. (Required) 100 | * `digest`: The cryptographic hash of this CASE. (Required) 101 | * `case` : The CASE object from the case.yaml (Required). See [case.yaml](100-case.md). 102 | 103 | Example: 104 | 105 | ``` 106 | specVersion: 1.0.0 107 | created: 2019-09-30T16:00:00.45234224-06:00 108 | digest: "sha256:4684ee693b6c5caf9d717cbaa06338d8e19841c39091c90295deb76d567810ec" 109 | case: 110 | apiVersion: v1 111 | version: 1.0.0 112 | appVersion: 1.0.0 113 | appSemver: 1.0.0 114 | name: etcd-operator-case 115 | displayName: "Sample IBM certified container CASE" 116 | description: "Sample IBM certified container CASE" 117 | webPage: https://github.com/coreos/etcd-operator 118 | organization: "coreos" 119 | catalogs: 120 | database: {} 121 | certifications: 122 | container: {} 123 | classifications: 124 | opensource: {} 125 | experimental: {} 126 | sample: {} 127 | supports: 128 | architectures: 129 | amd64: {} 130 | ppc64le: {} 131 | s390x: {} 132 | k8sDistros: 133 | rhocp3: {} 134 | managedPlatforms: 135 | ibm: {} 136 | icons: 137 | - url: https://raw.githubusercontent.com/CloudCoreo/etcd-cluster/master/images/icon.png 138 | mediaType: image/png 139 | ``` 140 | 141 | ### Semver and Semver Comparison Formats 142 | This specification uses the [Semantic Version 2.0.0 specification](https://semver.org/) (semver) for describing versions of entities. 143 | 144 | #### Non-functional CASE versions 145 | 146 | As stated in the [case.yaml specification](100-case.md#version), CASE supports non-functional versions. These are specified after the standard version and are prefixed with a plus sign (`+`). In order of preference, non-functional versions come after a standard release. The CASE repo currently only supports non-functional versions in the following date/timestamp format: `YYYYMMDD.HHmmSS`. For example, `1.0.0 < 1.0.0+20191008.162055`. If a non-functional version is specified in any other format, it will be ignored for purposes of version comparison. 147 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CASE Specification 2 |

3 | 4 |

5 | 6 | The Container Application Software for Enterprises (CASE) specification defines metadata and structure for packaging a containerized application. CASE provides a common packaging definition for the many ways to install, manage, operate, upgrade, and uninstall complex software using multiple roles and personas. It provides the flexibility to allow both simple and tailored use cases with a transparent and obvious security posture. 7 | 8 | ### The specification includes 9 | - Definition and specification of CASE artifacts 10 | - Deployment/Installation of CASE artifacts 11 | - Operation of CASE artifacts 12 | - Multi-persona activities 13 | - Authenticity and Integrity of a CASE 14 | - Compatibility with Out of scope work (futures) 15 | - Extensibility 16 | - Assembly of a CASE into a single file, archive or package for storage and transport 17 | 18 | ### Out of scope 19 | - Storage of a CASE 20 | - Transfer of a CASE 21 | - Entitlement of a CASE 22 | - Catalog / Display of CASEes 23 | 24 | See the [CASE Specification Index](000-index.md) for the specification documentation. 25 | 26 | ## Specification Status and Schedule 27 | **This specification is in beta and is updated regularly.** 28 | 29 | The master branch contains the live code changes for the NEXT version. See branches for snapshots of previous versions. 30 | 31 | **Specification Version: v1.1.0** 32 | 33 | ## Setting up Microsoft Visual Studio Code for Intellisense 34 | [Microsoft Visual Studio Code](https://code.visualstudio) with some extensions can simplify and validate building the CASE yaml files. 35 | 36 | To configure your VS Code project to use CASE YAML validation: 37 | 1. Install the [Red Hat YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml). 38 | 2. Clone this repository into a peer git repo to your project: 39 | `git clone https://github.com/ibm/case` 40 | 41 | 3. Create a soft-link to the `schemas` directory from this project into your own project: 42 | ``` 43 | cd myrepo 44 | ln -s ../case/schemas 45 | ``` 46 | 4. Copy the `.vscode/settings.json` folder/file from this project into your own project. This will add the correct mappings to support the CASE JSON schema files included in this project. 47 | -------------------------------------------------------------------------------- /design/case-overview-olm-sig-20200121.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/case/36406bf1baea6ad90d3347731679d22d6be00a6f/design/case-overview-olm-sig-20200121.pptx -------------------------------------------------------------------------------- /design/case-resource-retrieval.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/case/36406bf1baea6ad90d3347731679d22d6be00a6f/design/case-resource-retrieval.drawio.png -------------------------------------------------------------------------------- /design/case-signature-flow-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/case/36406bf1baea6ad90d3347731679d22d6be00a6f/design/case-signature-flow-diagram.png -------------------------------------------------------------------------------- /design/case.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/case/36406bf1baea6ad90d3347731679d22d6be00a6f/design/case.png -------------------------------------------------------------------------------- /samples/case-repo-sample/etcd-operator-case/1.0.0/etcd-operator-case-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/case/36406bf1baea6ad90d3347731679d22d6be00a6f/samples/case-repo-sample/etcd-operator-case/1.0.0/etcd-operator-case-1.0.0.tgz -------------------------------------------------------------------------------- /samples/case-repo-sample/etcd-operator-case/1.0.0/version.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | created: 2019-09-30T16:00:00.45234224-06:00 3 | digest: "sha256:4684ee693b6c5caf9d717cbaa06338d8e19841c39091c90295deb76d567810ec" 4 | case: 5 | version: 1.0.0 6 | appVersion: 1.0.0 7 | specVersion: 1.0.0 8 | name: etcd-operator-case 9 | displayName: "Sample IBM certified container CASE" 10 | description: "Sample IBM certified container CASE" 11 | webPage: https://github.com/coreos/etcd-operator 12 | organization: "coreos" 13 | catalogs: 14 | database: {} 15 | certifications: 16 | container: {} 17 | classifications: 18 | opensource: {} 19 | experimental: {} 20 | sample: {} 21 | supports: 22 | architectures: 23 | amd64: {} 24 | ppc64le: {} 25 | s390x: {} 26 | k8sDistros: 27 | rhocp3: {} 28 | managedPlatforms: 29 | ibm: {} 30 | icons: 31 | - url: https://raw.githubusercontent.com/CloudCoreo/etcd-cluster/master/images/icon.png 32 | mediaType: image/png -------------------------------------------------------------------------------- /samples/case-repo-sample/etcd-operator-case/index.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | latestAppVersion: 1.0.0 3 | latestVersion: 1.1.0 4 | versions: 5 | 1.0.0: 6 | appVersion: 1.0.0 7 | 1.1.0: 8 | appVersion: 1.0.0 9 | -------------------------------------------------------------------------------- /samples/case-repo-sample/index.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | entries: 3 | etcd-operator-case: 4 | latestAppVersion: 1.0.0 5 | latestVersion: 1.1.0 6 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | This CASE shows how the etcd-operator project could be converted to a CASE. Some pieces of this project are intentionally inefficient in an effort to show specific scenarios for a CASE. 4 | 5 | ## Prerequisites 6 | 7 | - Kubernetes 1.11 or later 8 | - Helm 2.13 or later 9 | 10 | ## Resources Required 11 | 12 | - At least 1GB of persistent storage, minimum 150m CPU and 256MB memory available for resource requests. 13 | 14 | ## Installing the CASE 15 | 16 | The CASE has the following inventory items: 17 | 18 | - `clusterSetup`: Contains the cluster-level Kubernetes resources required to deploy the Operator 19 | - `namespaceSetup`: Contains the namespace-level Kubernetes resources to prepare a namespace for the Operator's controller pods 20 | - `etcdOperators`: The etcd-operator Helm chart 21 | - `etcBackupExample`: A sample etcBackup custom resource 22 | - `etcClusterExample`: A sample etcCluster custom resource 23 | - `etcRestoreExample`: A sample etcRestore custom resource 24 | 25 | ## Configuration 26 | 27 | See each inventory item for specific configuration information. 28 | 29 | ## Limitations 30 | 31 | - This product is limited to install on amd64 32 | 33 | ## PodSecurityPolicy Requirements 34 | 35 | The predefined PodSecurityPolicy name [`ibm-restricted-psp`](https://ibm.biz/cpkspec-psp) has been verified for this chart. If your target namespace is bound to this PodSecurityPolicy, you can proceed to install the chart. 36 | 37 | Custom PodSecurityPolicy definition: 38 | ``` 39 | 40 | apiVersion: extensions/v1beta1 41 | kind: PodSecurityPolicy 42 | metadata: 43 | annotations: 44 | kubernetes.io/description: "This policy is the most restrictive, 45 | requiring pods to run with a non-root UID, and preventing pods from accessing the host." 46 | #apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default 47 | #apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default 48 | seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default 49 | seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default 50 | name: ibm-restricted-psp-etcd 51 | spec: 52 | allowPrivilegeEscalation: false 53 | forbiddenSysctls: 54 | - '*' 55 | fsGroup: 56 | ranges: 57 | - max: 65535 58 | min: 1 59 | rule: MustRunAs 60 | requiredDropCapabilities: 61 | - ALL 62 | runAsUser: 63 | rule: MustRunAsNonRoot 64 | seLinux: 65 | rule: RunAsAny 66 | supplementalGroups: 67 | ranges: 68 | - max: 65535 69 | min: 1 70 | rule: MustRunAs 71 | volumes: 72 | - configMap 73 | - emptyDir 74 | - projected 75 | - secret 76 | - downwardAPI 77 | - persistentVolumeClaim 78 | ``` 79 | 80 | ## Red Hat OpenShift SecurityContextConstraints Requirements 81 | 82 | This chart is supported on Red Hat OpenShift. The predefined SecurityContextConstraint name [`restricted`](https://ibm.biz/cpkspec-scc) has been verified for this chart. 83 | 84 | Custom SecurityContextConstraints definition: 85 | ``` 86 | apiVersion: security.openshift.io/v1 87 | kind: SecurityContextConstraints 88 | metadata: 89 | annotations: 90 | kubernetes.io/description: "This policy is the most restrictive, 91 | requiring pods to run with a non-root UID, and preventing pods from accessing the host." 92 | cloudpak.ibm.com/version: "1.0.0" 93 | name: ibm-restricted-scc-etcd 94 | allowHostDirVolumePlugin: false 95 | allowHostIPC: false 96 | allowHostNetwork: false 97 | allowHostPID: false 98 | allowHostPorts: false 99 | allowPrivilegedContainer: false 100 | allowPrivilegeEscalation: false 101 | allowedCapabilities: [] 102 | allowedFlexVolumes: [] 103 | allowedUnsafeSysctls: [] 104 | defaultAddCapabilities: [] 105 | defaultPrivilegeEscalation: false 106 | forbiddenSysctls: 107 | - "*" 108 | fsGroup: 109 | type: MustRunAs 110 | ranges: 111 | - max: 65535 112 | min: 1 113 | readOnlyRootFilesystem: false 114 | requiredDropCapabilities: 115 | - ALL 116 | runAsUser: 117 | type: MustRunAsNonRoot 118 | seccompProfiles: 119 | - docker/default 120 | seLinuxContext: 121 | type: RunAsAny 122 | supplementalGroups: 123 | type: MustRunAs 124 | ranges: 125 | - max: 65535 126 | min: 1 127 | volumes: 128 | - configMap 129 | - downwardAPI 130 | - emptyDir 131 | - persistentVolumeClaim 132 | - projected 133 | - secret 134 | priority: 0 135 | ``` -------------------------------------------------------------------------------- /samples/etcd-operator-case/case.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 1.0.0 2 | name: etcd-operator-case 3 | displayName: Sample IBM certified container CASE 4 | version: 1.0.0 5 | appVersion: 1.0.0 6 | description: "Sample IBM certified container CASE" 7 | icons: 8 | - base64: iVBORw0KGgoAAAANSUhEUgAAADcAAAAoCAYAAAEtXFKeAAAAAXNSR0IArs4c6QAAES5JREFUaAW1WQl4VEW2/u/S3dkTCEtCYpDNJyAIojGRLSCLLIoCQRZRiM8gCgICgvqBAdRRB2fmkw9hHJUZwI2go2JEBMeFkIWwSCCAsgVCQrZOutN73+2dukk3nZAO8J6v8t3curWdOtt/TlULaCpD75/VJz7h9qTySyev+Nr09/jJi7QhIx7Taqot2obPFmhUQlgH92jGujE2S+2euuoqZKyrxg9f1SM6VkD8LQbwHJQTHAd07nsKE/plYn7GZJw/GD91zZx8aqXy7j92arXmei05dar+6I2B/5JTphwL/GZ17pGZK3c11NdNtFnq8MBsDaOHTsLQfo/rS7JOjTqxN2czVn84GBfPuNExwYBbuhsB1jkp804tY/Ugze09ry3480DNt7yoOd3t7PXJ9dZzLgwb/gI0rudA4Kje37hdqo6fvHiLx+Wc43E74XW7fZPBcVxuYV72UH9DU0Vkb0bW43b5+3bv+TO27F6KpdM+Z21DbK5K7ctDi2GXKmo1VauEyo/nZjy5tt7tcsawiRxvw+D008jfZ4fRxCN1dBjKiqOw4ulliIhwYPXm19Cug3Dxldn5t+pbZRRFHqi3lkMVy6F5Q9BQE4Jlzz+JjZu2w+uVcDB/p58tto1mH6MnzNdcTpufR47jUZinETvZChvcZkkZOv2l5JSpb7Y5iDr9FMc9vFBzOezwuFxQFFmfRxIlitn+MYGLEWfAQ9OWaaqq+tvZhPXvPooZz3bEn/6VrimyVuXvbKpw6U+sshCVaCZV0iNkrwd/+/ss9Ejsj5jwRH3Y8bIvUFLxOertZbVQtc+eGZO7gCau1tgE38QPP34C5oYLyDuzGUf3KyQoBaZQHuGRPCJieETFCIiJ5XuQxPwmhmkrz2H52sVQJA3JI8Kpx4WZD85EWsoYPJOVSZ7DQbBzUc88mmsTSev6duLuOIA9OxoXMZhUzJ+wFt4xJmzdtwofLNiDf79/qJmQRE1R3qaZSxMM83C5ahf5oQSbOQQrlx9AYmIHfL2rA9kr8ppk0vz1+vqt2vf78rVho+Zoe/bmagMGTfK75733TbvKS8A0P/kHHlqY73bZU5rpEVxpYX52t4Dx/qp/or+FKmkPL44Rve4Dmqr08XjIICTZbxRsHM8LIL1XKhw/5HDeZ+cC516v3ozgpEdfOClJnt6KLEOWJCiyBJmeQILMwJhhDRuajEED7yCb5XDy5Bn7urXPxVD7dX1BJzglY2V3zcufk73eRgKtEOzaNR4bNj6HT/esR+aUN2AUIq5hZsfPL2LYgBnoGNF/vChyu68ZQA1cVlYWf+oSp3jJwnXOGEcBBL0eD7796h/4vHAJMsb+HaVXjuPW+H64XHcER0q3odxSpG/S4zSgoU6D3abQfBWCyMEYwsFE+BMSxiE0nIdBxALxVBl3QG1y2pY7UhQOSbcJ2Fk8GU5YseSvKYTIHmhkRxyvIYK8JamXCZ26GMkZFMiqBF5UEZcYgnpzo3RJ4hANPKlFXbFkYt5G2ge+JEIpgcS69TOj64CLyN/rhIsG7PqY/I6wIXlkOELCDbBdaYfn5sxFz6Q0KGqIrlNVtSH32IfIyd+FqnIFgqB9JHuFp96Yl38Vq5lIGaHpT64j/3c0iVKBMW4fEWj0UN9GGFchoRwRVGAwcfA4edSVh8FS3g6KO4JZLYmRR8GBz/Q1ffNavgXWcOLoj2vuGJCWxfAwMjIUVaVRmDB8Nl5/8W0otkT8vLsSQwZOwhsvbYDW0BPffFqBK2ci4bFGQ5UNtIJGHInXJcZoNdvN2MmL4w2CWGEg/by8IgOLl71JqOeGyJMOguiZ+aQmS6mFhV8UsAWvV5oRDBycnp4u1FgjX5Ul7zxN0dr5CJLoHBynfSxy3qUHDnxtC5xzI/WgBNnk1NT0UC7EMEbxSBmqqoUKAveBgzN8fzz34/obWbzlmFaJjZ44/3mVkJkhDaEOmbNEbtCIpwxhWISl4P+3wvwdS1ou2NZ3M2Jj05e0FxTVLJGTy+T0VyHtKrHAxXheJK+T7ig68HlJYHuwup/YI48+f5vKib+xcMg4CUbM7fag262JuH/kYHTp0hnV1WZycjn9uWcf2xmMiK9dd67MzEwDbwj9jUFYsMKIT5k8FgcLP0LaFMAa8i0q5V2wR+RAjP852yWZKSZqS4PNZ+16omZ2daqUZW/QcR5Km3IIO7ftW4Qq82AsnvXuNWNrLBewMy9zPaUfLxFmxl4zgBq46XNW3iqr4gWJIoIfpAPEKElebNqQhV1HF2HZjB34pvBNTB36arO1VFVGheUYAXeRduTCJ1xoSKTXLdlsZFUOsqvT5Pvbnh6xfzvBach2TZOaTQ78aN8uGk5jAV5+PAf7iv6lE3JLVrA86GTFl7C5r5CORdgtPBrqVc5DqQ7gMhqMfKwplIs1mbgkUxg/5r1f0raJvCAMVpQgxMjaV7+0EGer30HPhBQ0cAXY+MNmOBtEXDqrwFwl6RgpirKO+AYjB/aYTCxaNMFUkwm67DKlSE3+E8iNr67QJmuFz2GVi/H+7rk4eciNBqtMmMgTCNOhhA4FSb1CdcC21FOGZJEpt+bQMc6EitKrDBAYSIvG50aJGosnLYoi8xg0thK9Blnwzd4SlJ2TiACIC00/cfQZFIrSs05UntdgiuuLEf3SkJTQg6C5Hr9fOIVNn26j2GcgLpmxqyuWPZz7FiNBYiQEp8jtK6rMIX3FCRz62YFvtskgvNUJkfwx4sFo/JRjRYx7ONZkPA6T8RbaAGWStGYlRfXPftiIsqpKtIsVq6lt7iuP533rW5e9RdKXhd4xvsa7J5xGzkcWPeQzQqywRPue4eEoL+6IzZTChpnugldy4Gz5Hhw68y1KzpWg4rwRFadisffLIj9QNM6++l8kG1hFnxt8TcfzQiGEU6t2dQ5FGuR+Z0dY5BksXb+GXESDw2JETWkkZFsHytx7kAQYdmo7fOu09tZXnDZ3jR65GfCmJPfFwYPFcKsVhHuMaRWaZITsoRShXkOXuASMHJGCznHtkZPzE86eu0j5Jq/nnJI72nj48HtXddKCoo4gssf939T+Pus7fOQUwsPD8Oqy1xAdFYFVWe8Q/tXitbXPIimpC16h763bvyDzNur5CCPEiqIoW9oixMb4ZTU7c02e3eZIfX/jy3j9rfeRe+AIViydi+HD7sZrr2/Cvh/y/ATYxMBCYaeajlidA9taq/uJsc6JU5/f4/V6xmxYvxxZr27C+fOXaPcaCGH98azlIkToLBHq1bK9te9mxNiAsZMWjqKD3l6JjmptxTM9B9HUeUTovdYWbq3tGmK+QSPHPHWfonjflmQ5xccZAwCK2CW8xr9YULBjl2/sjb6DEgu2QFraMxFciDSSnG8SJUJDSApdSdAmSoz0TKwRkVjq0Li0qioMoirIPA7R+xtNRk5RUXZlsPX/yPYbYu6Bh56dTpt7hZ7bZQoSLPTRMY/4U+lpfGvEA6v7cqNgm2zMmSjtVBWzpnF/ETjtr/n52c0y92Bzb7Y9KHMTpizpTm77Cekg2UtJHWkIlOQ1MUTm8r9gjtyf0ilag4KbjzCzbUVVKi31ljllpfv33CwDbY330fCPSU9fHieJ/PekpX6Uh1/VzE0yxzTo8XjRqVMsRo8agvFj09Cz5y0UcDyw2qvR4DDrZixQxIwKb4eYyDgICCepCSeI348IDreSlv9P5tuMuUdmvrREEIW/MCTRNRVodjfIHGMoMaEzVr28APck98ae/H9i/5GvEBfbHXf3GY3but5FjHSi4KvHA12ozJxtzjpcrCrG8fN7UVl/Gv17pWHkwHkU5EPzKR15ihi9oQzcryWq+ClMfWLVJjKRpyXP1RvJwIHXqxPKIaFLJ2zeuA4evgwffr0cdn4WUu+cAId6Fl6tDoP6jIRRDLtmKWaa0REd0T/ifvTvcb+/v+TiXuw/uTF11KBFJ2TFa62wHJn2acHCYoMQwkWIXrXOITpjEtzueXcfbjWk6ppLn7N6uSAY3pK8br9f3YzmnE4XMp6YgmfnT8PGr+agb9eRSBswF9n/eZ1u7y7h6Yc3+zccWHF5Lah3XEB1w2n9qaO63VMNr2wjvyTQItPmYSTz5SB5ZdobT27C0ZvwmfISBk4smrNLE9FAdYGxo9VS54deIWwtl56ZlUTXcicIwiN1wGgCjRtljjE2fdp4PL94BjblzMDEe1YhqdMAPw9WZxkumYvY4QA1ttNweGsIQNhhg4fXJcBpBxwNKr3JR90qpZqNyS2LJGzTLEMWadPMillCy7M2+va1+8cQc41MAmERIlRJe1HkFX4OL/CRMiHizRY6AiMyPBKzp0/BL6c3ICYmEkcvb8F3JcWQVLp/kQTYrTzMlQrqahQ49OspJnLSCBMy/WNvtilTCE/XVByi2gl0ZcXTd6M2GJMkb7qzZQIgxGaZZJDCzh0sO/e4lEWLJ+S+Q8tiue9WIsicZs0aMwvK3mMT3OidWo+EXg5knxwFt0NEzWUVV8q8sNYR3FPc42nnjCDbkED1iGgeHeMN9IgIjyITI/Oy0lmltlqiuzmZBCFCctAPGyQwY0QkBGPjSclsNuNC+WW07yQgthNpJeDkwkyR/YZAAjtGefULzz2wn5C+sbAD1a8Uz4ZQrPG1tfpWiKH4HnYMHFVBt90eVBEjF37z4sQxdudAmmCMMG1QYccmpo3EbkZ0722iW3KOmHbj4lkPqi8RY0o8buvbF31690OXzt0RFtKB5ofRVii4azytQ5vVXKi1HsKx3wvwY9ElxCcJlNWyownzLeZvKCaf26I5jdtXzv6pVifc4h9dqCOL2vaxSa0V5sRx3a24a8xZnC1x45fdLEMhi2J0mgrzAVaYkzPHvpfuF9n7aJ4NvxdF48FRQ/HIQ33RProfHeI66kww02ycRYFdsaOu4Xdcrj2OM+WHUVp5BnUWK9xOAhKPYCZGfqar3S9VTdn35vyDV5rIXvfF1uemzX1lH0lrpB60WwAKL8gIiy+Cg35m8R00gq3KmGNXvZFRBBQOCX3+qxvuu2sAjEYDMeCBm859NlcDLPY6/bHa7LDR0dpWL8JRF0I/NoTCWR8Cr9NIJsu0qNVQttf36NHsmmA022rXhTc9I6uLoqjHCDE7sLyR5Yw+tGTfHrpKEUOrYYqqAm9wkh8xEyZOGkUfsD6ZJuth500yL0WmnxMIVBgquh0GeMgvFY8JIcZIdOzQCbHt2blYRV29BVV0epMkxW/azDQpTRtXlJ/9XQCBm6r6t8cYlCTpMEk/jp1zGIMeusdbkJmO4UMGIq+wGNs/zsH5C+UQRRFJiZ0R37kDJBrrdJI/lZajlhxfot9LGHgkUP+QwXdhzOgh6N4tUb96yy/8Ffv3H8Lp386TJTjJEgRaK8C+/VvnVY5TxxXm7fSDg7/rJip+5hrnZPGPzHRTTifMcjoduhQjwkxIvpsuRui42pvMzG53Ip8O6D/8pwBHfz1FvzDwuIf6x40dhgF33k5alpBfcBR79x5A8fHf0NBgp7jE6wJhQbetwpilVKxE8RrSDh/+pFWQaGt+y75WqZ07dy4pKib26z+t33rnmTMXKHaIqDNb0P+OXhiccie+zvkRV67U4LGZE1FWVkHM/IrqKjOZkUIBV9SRsyWhtr45lmZomllRtamHCnb+1NbYm+lrlTnfAqnpS0Lbq9pauuZaTMRFdtNktzuYo5Nvabrp3ux5zrc28ymmSTL/XYQdCw7nZl/y9f1R7zaZCyQybtxCk8xJ0yiEPU2/caXytDMW/BsfOqQGPayy+Nf4MKHQ3++cpv3TxSkfFOf9uzqQxh9dv2HmghDm7k2blUB770pcJmqSEkds3kpareI5vpzQrsLACaVWq1pWUpLtDbLG/1vz/wBBrimFdr5QEgAAAABJRU5ErkJggg== 9 | mediaType: image/png 10 | url: https://raw.githubusercontent.com/CloudCoreo/etcd-cluster/master/images/icon.png 11 | organization: "IBM" 12 | 13 | supports: 14 | architectures: 15 | amd64: {} 16 | k8sDistros: 17 | rhocp4: {} 18 | managedPlatforms: 19 | ibm: {} 20 | redhat: {} 21 | 22 | certifications: 23 | ibmccs: {} 24 | 25 | catalogs: 26 | database: {} 27 | 28 | classifications: 29 | opensource: {} 30 | experimental: {} 31 | sample: {} 32 | 33 | webPage: "http://ibm.com" 34 | 35 | licenses: 36 | apache2: 37 | ref: license 38 | url: https://www.apache.org/licenses/LICENSE-2.0.txt 39 | mediaType: application/text 40 | metadata: 41 | displayName: Apache 2.0 42 | displayDescription: Apache License, version 2.0 43 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/certifications/ibmccs.yaml: -------------------------------------------------------------------------------- 1 | certification: 2 | metadata: 3 | name: ibmccs 4 | displayName: Certified container software 5 | id: some-autogenerated-id 6 | provider: ibm 7 | type: ccs 8 | issueDate: "10/01/2019" 9 | expirationDate: "03/31/2020" 10 | terms: "Valid from date of issue. Security vulnerability management and enhancements are delivered on the latest version of the chart and images" 11 | exceptions: 12 | - id: "12345" 13 | description: "Non RedHat certificated operator : UBI image unavailable for community operator, verified manual per standards and supported by IBM" 14 | remediation: "Contribute UBI based image to community operator and RedHat Certify with next release" 15 | 16 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/digests.yaml: -------------------------------------------------------------------------------- 1 | 2 | digests: 3 | digestDefs: 4 | case: 5 | digest: sha256:08f71188c74d4bc5c4017d0ea550fbf491384c0020018802ff16098ebc727d5a 6 | size: 21547 7 | skip: false 8 | inventory: 9 | clusterSetup: 10 | imageManifest: {} 11 | readme: 12 | digest: sha256:0cfb2abe7b978dadd42d39df7b5c1737876b2b5a9bd71e701306fd7ed52c0c1c 13 | size: 837 14 | skip: false 15 | resources: 16 | resourceDefs: 17 | files: 18 | - digest: sha256:fc06169a8c205532a8f71d83dc3d8e9d3964daa53811771a1ee8e3cd1dab70dd 19 | size: 474 20 | skip: false 21 | - digest: sha256:8e141837b59ee95e48406303ec8df233fdac04781cb3fff3f031a3371d614036 22 | size: 237 23 | skip: false 24 | - digest: sha256:9e85c9d58f41d7be8c14a88460c57fa6e22e3ffb7a35ac46fe6dbf33cfe719bb 25 | size: 864 26 | skip: false 27 | - digest: sha256:1d30479d78d20016f72732414efa43eccf88e9df776ce017d6d2af1599c90bbe 28 | size: 1074 29 | skip: false 30 | - digest: sha256:e919212a5add286aae08c47261efd47124ba0ce66763fca8092c7e312c98e15c 31 | size: 412 32 | skip: false 33 | - digest: sha256:4593340c09b9c703462c53303886ce84565ba2f8fb25ecb01908765d11398b17 34 | size: 444 35 | skip: false 36 | - digest: sha256:ff729701b5c9ff97bd8721294d165a70bd3f2990c1157586901529f9840ae50b 37 | size: 417 38 | skip: false 39 | etcdBackupExample: 40 | imageManifest: {} 41 | readme: 42 | digest: sha256:dda3e160dfcb26b56c627ff8a96d7f7ab29f9ac3455aea9d97700a3ba1f55611 43 | size: 72 44 | skip: false 45 | resources: 46 | resourceDefs: 47 | files: 48 | - digest: sha256:892f3b670216151012ceef3ff5a582116d60b8a663a3b8d17c05aec66dbbd354 49 | size: 339 50 | skip: false 51 | etcdClusterExample: 52 | imageManifest: {} 53 | readme: 54 | digest: sha256:5df4eddafd859022f24a29e4c495402ca5fb58e5ab2e4a27a97a42c7005d7179 55 | size: 74 56 | skip: false 57 | resources: 58 | resourceDefs: 59 | files: 60 | - digest: sha256:3286ad491bf102c0c1c038750dd2270295929a6cf73012f8e300aa6f61ecbf93 61 | size: 323 62 | skip: false 63 | etcdOperators: 64 | imageManifest: {} 65 | readme: 66 | digest: sha256:26d89d49cb345fa48db2e2b9b996e4b31d48d0670a4e818129c47c286e431379 67 | size: 404 68 | skip: false 69 | resources: 70 | resourceDefs: 71 | helmCharts: 72 | - digest: sha256:4a78bd155b4fb8af9da57b6fd55b22b459b9d39f0ad5794821952f2c26a37452 73 | skip: false 74 | etcdRestoreExample: 75 | imageManifest: {} 76 | readme: 77 | digest: sha256:dda3e160dfcb26b56c627ff8a96d7f7ab29f9ac3455aea9d97700a3ba1f55611 78 | size: 72 79 | skip: false 80 | resources: 81 | resourceDefs: 82 | files: 83 | - digest: sha256:012936ba557ef07c0b381e153a795d5ebfbb26e4919e7094215804364d85d61b 84 | size: 468 85 | skip: false 86 | namespaceSetup: 87 | imageManifest: {} 88 | readme: 89 | digest: sha256:1570769c6f2dec9c2b997946ac91232d0fe2c99fecd4acbce8973b368b4c9cc5 90 | size: 752 91 | skip: false 92 | resources: 93 | resourceDefs: 94 | files: 95 | - digest: sha256:fd8b757cfa57093fffcc81dca520a1a9dac4acfde03aa2d5aa368ad95bcc1a1c 96 | size: 110 97 | skip: false 98 | - digest: sha256:fcca09305d83eaca8c2a646d47d5885e90cc384a4868864965d1ae5541c9c886 99 | size: 305 100 | skip: false 101 | - digest: sha256:fb49166df5fadcec85412b0a29e3b3b0e1110a17ccfd95e2ce0a6e6e030c11b4 102 | size: 120 103 | skip: false 104 | - digest: sha256:328e58c4be544d84282604e4eb19f3175d2a5f9efcf70531a698817cffa06234 105 | size: 334 106 | skip: false 107 | license: 108 | digest: sha256:58d1e17ffe5109a7ae296caafcadfdbe6a7d176f0bc4ab01e12a689b0499d8bd 109 | size: 11357 110 | skip: false 111 | licenses: 112 | apache2: 113 | digest: sha256:43070e2d4e532684de521b885f385d0841030efa2b1a20bafb76133a5e1379c1 114 | size: 11356 115 | skip: false 116 | readme: 117 | digest: sha256:4e150a985042896fd9a680f9513a940516049ac5223261cb0c0efb492ea78958 118 | size: 3038 119 | skip: false 120 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/README.md: -------------------------------------------------------------------------------- 1 | # etcd Cluster Setup 2 | 3 | This readme provides instructions on how to install and configure the Kubernetes cluster to run the etcd Operator using the `cloudctl case launch` framework. The installer can be ran using the `cloudctl case launch` command. The launch install script takes the following parameters that must be passed in via the `--args` flag in the `cloudctl case launch` command (note the args are a comma separated value list of arg=value format): 4 | 5 | | arg name | type | description | required | 6 | |----------|------|-------------|----------| 7 | | imageRegistryUser | string | image registry username to generate the pull secret from | yes (if images in a password protected registry) | 8 | | imageRegistryPass | string | image registry password to generate the pull secret from | yes (if images in a password protected registry) | 9 | | createNamespace | bit | if 1, will create the namespace passed in through the `--namespace` flag to `cloudctl`, if 0 will assume the namespace has been precreated | no | 10 | | imageRegistry | string | registry name where the images are to be pulled from (ex quay.io) | yes | 11 | | pullSecretName | string | name of the pull secret to be created (used later in the productInstall step) | yes | 12 | 13 | This is the second step in the installation process, and should be ran before `productInstall` and after `loadAirgapResources` launcher actions are executed. 14 | 15 | ## Prerequisites 16 | 17 | This CASE is supported on IBM Kubernetes Service (IKS), IBM Cloud Private (ICP) or Red Hat Openshift Container Platform running Kubernetes 1.11.0 or later on amd64 Linux. 18 | 19 | ## Sample Command 20 | 21 | ```raw 22 | $ cloudctl case launch -c \ 23 | --namespace install-namespace \ 24 | --instance demo \ 25 | --inventory clusterSetup \ 26 | --action setup \ 27 | --args "imageRegistryUser='testuser@email.com',imageRegistryPass='P@ssw0rD',createNamespace=1,imageRegistry='quay.io',pullSecretName=my-pull-secret" 28 | ``` 29 | 30 | 31 | ## Installation 32 | The Cluster Setup includes the cluster-scoped Kubernetes resource required to install the etcd Operator. 33 | 34 | ### Roles required 35 | 36 | - Cluster Administrator 37 | 38 | ### Steps (manual) 39 | 1. Login to kubectl as a cluster administrator. 40 | 1. `cd inventory/clusterSetup/files` 41 | 1. `kubectl apply -f .` 42 | 43 | A namespace administrator can now install the Helm chart in `inventory/ectdOperators` with the create custom resource definition parameters set to false. 44 | 45 | ### Steps (case launch) 46 | 47 | 1. Login to kubectl as a cluster administrator 48 | 1. `$ cloudctl case launch ` 49 | 50 | 51 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/actions.yaml: -------------------------------------------------------------------------------- 1 | actions: 2 | metadata: 3 | name: clusterSetup 4 | description: The actions required to install the etcd cluster resources 5 | # Install the cluster prerequisites 6 | actionDefs: 7 | setup: 8 | metadata: 9 | name: "setup" 10 | description: "Performs the cluster setup" 11 | case.launcher.type: "script" 12 | roles: 13 | - clusterAdmin 14 | 15 | requires: 16 | and: 17 | - "/case/prereqs/k8sDistros/kubernetes" 18 | - "/case/prereqs/k8sResources/workerIntelLinux" 19 | - or: 20 | - "/case/prereqs/k8sDistros/ibmCloud" 21 | - "/case/prereqs/k8sDistros/ibmCloudPrivate" 22 | - "/case/prereqs/k8sDistros/openshift" 23 | 24 | # User must have the ability to create cluster roles and custom resource definitions 25 | k8sPermissions: 26 | rules: 27 | - rule: 28 | group: rbac.authorization.k8s.io 29 | resource: clusterroles 30 | verbs: 31 | - get 32 | - list 33 | - watch 34 | - create 35 | - patch 36 | - update 37 | version: '*' 38 | - rule: 39 | group: apiextensions.k8s.io 40 | resource: customresourcedefinitions 41 | verbs: 42 | - get 43 | - list 44 | - watch 45 | - create 46 | - patch 47 | - update 48 | version: v1beta1 49 | 50 | # Resolve this permission check ONLY if the prereq resolves to true. 51 | - ifExpression: 52 | "!": 53 | - "/case/prereqs/k8sDistros/openshift" 54 | rule: 55 | group: policy 56 | resource: podsecuritypolicies 57 | verbs: 58 | - get 59 | - list 60 | - watch 61 | - create 62 | - patch 63 | - update 64 | 65 | - ifExpression: 66 | "/prereqs/k8sDistros/openshift" 67 | rule: 68 | group: security.openshift.io 69 | resource: securitycontextconstraints 70 | verbs: 71 | - get 72 | - list 73 | - watch 74 | - create 75 | - patch 76 | - update 77 | 78 | install: 79 | metadata: 80 | name: "install" 81 | description: "Installs the etcd operator" 82 | roles: 83 | - clusterAdmin 84 | 85 | # must be iks, icp or ocp AND Kubernetes 1.11.0 or later running on amd64 Linux 86 | requires: 87 | and: 88 | - "/case/prereqs/k8sDistros/kubernetes" 89 | - "/case/prereqs/k8sResources/workerIntelLinux" 90 | - or: 91 | - "/case/prereqs/k8sDistros/ibmCloud" 92 | - "/case/prereqs/k8sDistros/ibmCloudPrivate" 93 | - "/case/prereqs/k8sDistros/openshift" 94 | 95 | # User must have the ability to create cluster roles and custom resource definitions 96 | k8sPermissions: 97 | rules: 98 | - rule: 99 | group: rbac.authorization.k8s.io 100 | resource: clusterroles 101 | verbs: 102 | - get 103 | - list 104 | - watch 105 | - create 106 | - patch 107 | - update 108 | version: '*' 109 | - rule: 110 | group: apiextensions.k8s.io 111 | resource: customresourcedefinitions 112 | verbs: 113 | - get 114 | - list 115 | - watch 116 | - create 117 | - patch 118 | - update 119 | version: v1beta1 120 | 121 | # Resolve this permission check ONLY if the prereq resolves to true. 122 | - ifExpression: 123 | "!": 124 | - "/case/prereqs/k8sDistros/openshift" 125 | rule: 126 | group: policy 127 | resource: podsecuritypolicies 128 | verbs: 129 | - get 130 | - list 131 | - watch 132 | - create 133 | - patch 134 | - update 135 | 136 | - ifExpression: 137 | "/prereqs/k8sDistros/openshift" 138 | rule: 139 | group: security.openshift.io 140 | resource: securitycontextconstraints 141 | verbs: 142 | - get 143 | - list 144 | - watch 145 | - create 146 | - patch 147 | - update 148 | 149 | # Remove the cluster prerequistes 150 | remove: 151 | metadata : 152 | name: "install" 153 | description: "Installs the etcd operator" 154 | roles: 155 | - clusterAdmin 156 | 157 | # must be iks, icp or ocp AND Kubernetes 1.11.0 or later running on amd64 Linux 158 | requires: 159 | and: 160 | - "/case/prereqs/k8sDistros/kubernetes" 161 | - "/case/prereqs/k8sResources/workerIntelLinux" 162 | - or: 163 | - "/case/prereqs/k8sDistros/ibmCloud" 164 | - "/case/prereqs/k8sDistros/ibmCloudPrivate" 165 | - "/case/prereqs/k8sDistros/openshift" 166 | 167 | k8sPermissions: 168 | rules: 169 | - rule: 170 | group: rbac.authorization.k8s.io 171 | resource: clusterroles 172 | verbs: 173 | - '*' 174 | - rule: 175 | group: apiextensions.k8s.io 176 | resource: customresourcedefinitions 177 | verbs: 178 | - '*' 179 | 180 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/files/etcd-resources/etcd-operator-clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: etcd-operator 5 | rules: 6 | - apiGroups: 7 | - etcd.database.coreos.com 8 | resources: 9 | - etcdclusters 10 | - etcdbackups 11 | - etcdrestores 12 | verbs: 13 | - '*' 14 | - apiGroups: 15 | - "" 16 | resources: 17 | - pods 18 | - services 19 | - endpoints 20 | - persistentvolumeclaims 21 | - events 22 | verbs: 23 | - '*' 24 | - apiGroups: 25 | - apps 26 | resources: 27 | - deployments 28 | verbs: 29 | - '*' 30 | - apiGroups: 31 | - "" 32 | resources: 33 | - secrets 34 | verbs: 35 | - get 36 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/files/etcd-resources/etcd-operator-psp-clusterrole.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRole 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: ibm-restricted-psp-etcd-cr 5 | rules: 6 | - apiGroups: 7 | - extensions 8 | resources: 9 | - podsecuritypolicies 10 | resourceNames: 11 | - ibm-restricted-psp-etcd 12 | verbs: 13 | - use -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/files/etcd-resources/etcd-operator-psp.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: PodSecurityPolicy 3 | metadata: 4 | annotations: 5 | kubernetes.io/description: "This policy is the most restrictive, 6 | requiring pods to run with a non-root UID, and preventing pods from accessing the host." 7 | seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default 8 | seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default 9 | name: ibm-restricted-psp-etcd 10 | spec: 11 | allowPrivilegeEscalation: false 12 | forbiddenSysctls: 13 | - '*' 14 | fsGroup: 15 | ranges: 16 | - max: 65535 17 | min: 1 18 | rule: MustRunAs 19 | requiredDropCapabilities: 20 | - ALL 21 | runAsUser: 22 | rule: MustRunAsNonRoot 23 | seLinux: 24 | rule: RunAsAny 25 | supplementalGroups: 26 | ranges: 27 | - max: 65535 28 | min: 1 29 | rule: MustRunAs 30 | volumes: 31 | - configMap 32 | - emptyDir 33 | - projected 34 | - secret 35 | - downwardAPI 36 | - persistentVolumeClaim -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/files/etcd-resources/etcd-operator-scc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: security.openshift.io/v1 2 | kind: SecurityContextConstraints 3 | metadata: 4 | annotations: 5 | kubernetes.io/description: "This policy is the most restrictive, 6 | requiring pods to run with a non-root UID, and preventing pods from accessing the host." 7 | cloudpak.ibm.com/version: "1.0.0" 8 | name: ibm-restricted-scc-etcd 9 | allowHostDirVolumePlugin: false 10 | allowHostIPC: false 11 | allowHostNetwork: false 12 | allowHostPID: false 13 | allowHostPorts: false 14 | allowPrivilegedContainer: false 15 | allowPrivilegeEscalation: false 16 | allowedCapabilities: [] 17 | allowedFlexVolumes: [] 18 | allowedUnsafeSysctls: [] 19 | defaultAddCapabilities: [] 20 | defaultPrivilegeEscalation: false 21 | forbiddenSysctls: 22 | - "*" 23 | fsGroup: 24 | type: MustRunAs 25 | ranges: 26 | - max: 65535 27 | min: 1 28 | readOnlyRootFilesystem: false 29 | requiredDropCapabilities: 30 | - ALL 31 | runAsUser: 32 | type: MustRunAsNonRoot 33 | seccompProfiles: 34 | - docker/default 35 | seLinuxContext: 36 | type: RunAsAny 37 | supplementalGroups: 38 | type: MustRunAs 39 | ranges: 40 | - max: 65535 41 | min: 1 42 | volumes: 43 | - configMap 44 | - downwardAPI 45 | - emptyDir 46 | - persistentVolumeClaim 47 | - projected 48 | - secret 49 | priority: 0 -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/files/etcd-resources/etcdbackups-crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: etcdbackups.etcd.database.coreos.com 5 | spec: 6 | conversion: 7 | strategy: None 8 | group: etcd.database.coreos.com 9 | names: 10 | kind: EtcdBackup 11 | listKind: EtcdBackupList 12 | plural: etcdbackups 13 | singular: etcdbackup 14 | scope: Namespaced 15 | version: v1beta2 16 | versions: 17 | - name: v1beta2 18 | served: true 19 | storage: true 20 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/files/etcd-resources/etcdclusters-crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: etcdclusters.etcd.database.coreos.com 5 | spec: 6 | conversion: 7 | strategy: None 8 | group: etcd.database.coreos.com 9 | names: 10 | kind: EtcdCluster 11 | listKind: EtcdClusterList 12 | plural: etcdclusters 13 | shortNames: 14 | - etcd 15 | singular: etcdcluster 16 | scope: Namespaced 17 | version: v1beta2 18 | versions: 19 | - name: v1beta2 20 | served: true 21 | storage: true 22 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/files/etcd-resources/etcdrestores-crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: etcdrestores.etcd.database.coreos.com 5 | spec: 6 | conversion: 7 | strategy: None 8 | group: etcd.database.coreos.com 9 | names: 10 | kind: EtcdRestore 11 | listKind: EtcdRestoreList 12 | plural: etcdrestores 13 | singular: etcdrestore 14 | scope: Namespaced 15 | version: v1beta2 16 | versions: 17 | - name: v1beta2 18 | served: true 19 | storage: true 20 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/files/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Installs the ectd-operator-case 5 | # Usage: install.sh [--caseJsonFile casejsonpath --inventory inventoryItemOfLauncher --action launchAction] 6 | # --args args --casePath casepath --instance instancename --namespace namespace 7 | # 8 | # The additional args parameters include: imageRegistry, imageRegistryUser, imageRegistryPass, and pullSecretName 9 | # 10 | 11 | # default values 12 | installType="all" 13 | createNamespace=0 14 | pullSecretName="default" 15 | caseJsonFile="" 16 | casePath="" 17 | inventory="" 18 | action="" 19 | namespace="" 20 | instance="" 21 | helmCSV="" 22 | regUser="" 23 | regPass="" 24 | imageReg="" 25 | pullSecretName="" 26 | 27 | 28 | 29 | print_usage () { 30 | echo "usage: install.sh [--caseJsonFile casejsonpath --inventory inventoryItemOfLauncher --action launchAction] --args \"--imageRegistry imageRegistry, --imageRegistryUser user, --imageRegistryPass pass, --pullSecretName secretName\" --casePath casepath --instance instancename --namespace namespace" 31 | if [ -z $1 ]; then 32 | exit 1 33 | else 34 | exit $1 35 | fi 36 | } 37 | 38 | # Parses the args (--args) parameter if specified 39 | parse_dynamic_args () { 40 | _IFS=$IFS 41 | IFS=" " 42 | read -ra arr <<< "${1}" 43 | IFS="$_IFS" 44 | arr+=("") 45 | idx=0 46 | v="${arr[${idx}]}" 47 | 48 | while [ "$v" != "" ]; do 49 | case $v in 50 | --createNamespace) 51 | idx=$(( idx + 1 )) 52 | v="${arr[${idx}]}" 53 | createNamespace="${v}" 54 | ;; 55 | --imageRegistry) 56 | idx=$(( idx + 1 )) 57 | v="${arr[${idx}]}" 58 | imageReg="${v}" 59 | ;; 60 | --imageRegistryUser) 61 | idx=$(( idx + 1 )) 62 | v="${arr[${idx}]}" 63 | regUser="${v}" 64 | ;; 65 | --imageRegistryPass) 66 | idx=$(( idx + 1 )) 67 | v="${arr[${idx}]}" 68 | regPass="${v}" 69 | ;; 70 | --pullSecretName) 71 | idx=$(( idx + 1 )) 72 | v="${arr[${idx}]}" 73 | pullSecretName="${v}" 74 | ;; 75 | --help) 76 | print_usage 0 77 | ;; 78 | *) 79 | echo "Invalid Option ${v}" >&2 80 | exit 1 81 | ;; 82 | esac 83 | idx=$(( idx + 1 )) 84 | v="${arr[${idx}]}" 85 | done 86 | 87 | # Check that all required parameters have been specified 88 | foundError=0 89 | if [ -z $imageReg ]; then 90 | echo "Error: The imageRegistry parameter was not specified with the --args parameter." 91 | foundError=1 92 | fi 93 | if [ -z $regUser ]; then 94 | echo "Error: The imageRepoUser parameter was not specified with the --args parameter." 95 | foundError=1 96 | fi 97 | if [ -z $regPass ]; then 98 | echo "Error: The imageRegistryPass parameter was not specified with the --args parameter." 99 | foundError=1 100 | fi 101 | if [ -z $pullSecretName ]; then 102 | echo "Error: The pullSecretName parameter was not specified with the --args parameter." 103 | foundError=1 104 | fi 105 | if [ $foundError -eq 1 ]; then 106 | print_usage 107 | fi 108 | } 109 | 110 | # Validates that the required parameters were specified 111 | check_cli_args () { 112 | foundError=0 113 | 114 | if [ -z $casePath ]; then 115 | echo "Error: The case path parameter was not specified." 116 | foundError=1 117 | else 118 | ls $casePath/case.yaml > /dev/null 119 | if [ $? != 0 ]; then 120 | echo "Error: No case.yaml in the root of the specified case path parameter." 121 | foundError=1 122 | fi 123 | fi 124 | 125 | parse_dynamic_args 126 | 127 | if [ $foundError -eq 1 ]; then 128 | print_usage 129 | fi 130 | } 131 | 132 | # Verifies that we have a connection to the Kubernetes cluster 133 | check_kube_connection () { 134 | kubectl get pods > /dev/null 135 | if [ $? != 0 ]; then 136 | # Developer note: Kubectl should be included in your prereqs.yaml as a client prereq if it is required for your script. 137 | echo "Error executing kubectl. Verify that kubectl is installed and you are connected to a Kubernetes cluster." 138 | exit 1 139 | fi 140 | } 141 | 142 | create_namespace () { 143 | if [ -z $namespace ]; then 144 | echo "Error: The namespace was not specified." 145 | print_usage 146 | fi 147 | set -e 148 | sed "s//$namespace/g" $casePath/inventory/namespaceSetup/files/namespace.yaml | kubectl apply -f - 149 | set +e 150 | } 151 | 152 | # Creates the resources specified in the clusterSetup inventory item 153 | cluster_setup () { 154 | echo "In cluster_setup" 155 | check_kube_connection 156 | isOCP=0 157 | if kubectl api-resources | grep securitycontextconstraints > /dev/null ; then 158 | isOCP=1 159 | fi 160 | set -e 161 | for clusterYaml in $casePath/inventory/clusterSetup/files/etcd-resources/*.yaml; do 162 | if [[ $clusterYaml == *-scc.yaml ]]; then 163 | if [ $isOCP -eq 1 ]; then 164 | echo "applying $clusterYaml" 165 | kubectl apply --validate=false -f $clusterYaml 166 | fi 167 | elif [[ $clusterYaml == *psp* ]]; then 168 | if [ $isOCP -ne 1 ]; then 169 | echo "applying $clusterYaml" 170 | kubectl apply -f $clusterYaml 171 | fi 172 | elif [[ $clusterYaml != */etcdclusters-crd.yaml ]]; then 173 | echo "applying $clusterYaml" 174 | kubectl apply -f $clusterYaml 175 | fi 176 | 177 | done 178 | set +e 179 | if kubectl get secrets $pullSecretName -n $namespace > /dev/null 2>&1 ; then 180 | kubectl create secret docker-registry $pullSecretName --docker-server=$imageReg --docker-username=$regUser --docker-password=$regPass --docker-email=$regUser -n $namespace --dry-run -o yaml | kubectl apply -f - 181 | else 182 | kubectl create secret docker-registry $pullSecretName --docker-server=$imageReg --docker-username=$regUser --docker-password=$regPass --docker-email=$regUser -n $namespace 183 | fi 184 | } 185 | 186 | # Runs the expected commands 187 | run_install () { 188 | echo "Executing clusterSetup" 189 | if [ $createNamespace -eq 1 ]; then 190 | create_namespace 191 | fi 192 | cluster_setup 193 | } 194 | 195 | # Parse CLI parameters 196 | while [ "$1" != "" ]; do 197 | case $1 in 198 | --caseJsonFile ) 199 | shift 200 | caseJsonFile="${1}" 201 | ;; 202 | --casePath ) 203 | shift 204 | casePath="${1}" 205 | ;; 206 | --inventory ) 207 | shift 208 | inventory="${1}" 209 | ;; 210 | --action ) 211 | shift 212 | action="${1}" 213 | ;; 214 | --namespace ) 215 | shift 216 | namespace="${1}" 217 | ;; 218 | --instance ) 219 | shift 220 | instance="${1}" 221 | ;; 222 | --args ) 223 | shift 224 | parse_dynamic_args "${1}" 225 | ;; 226 | --help ) 227 | print_usage 0 228 | ;; 229 | *) 230 | echo "Invalid Option ${1}" >&2 231 | exit 1 232 | ;; 233 | esac 234 | shift 235 | done 236 | 237 | # Execution order 238 | check_cli_args 239 | run_install -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/inventory.yaml: -------------------------------------------------------------------------------- 1 | # This file describes the contents of an inventory item, which can contain multiple artificats 2 | inventory: 3 | metadata: 4 | # Must match the parent inventory directory. 5 | name: clusterSetup 6 | 7 | # Human readable description 8 | description: The cluster resources required before installing. 9 | 10 | # The Kubernetes scope that this item applies to. Can be: "cluster" or "namespace" 11 | k8sScope: cluster 12 | 13 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/clusterSetup/resources.yaml: -------------------------------------------------------------------------------- 1 | 2 | resources: 3 | metadata: 4 | name: clusterSetup 5 | displayName: etcd Resources 6 | displayDescription: etcd Resources that require a cluster admin to create. 7 | resourceDefs: 8 | files: 9 | - ref: etcd-resources/etcd-operator-clusterrole.yaml 10 | mediaType: application/vnd.case.resource.k8s.v1+yaml 11 | - ref: etcd-resources/etcd-operator-psp-clusterrole.yaml 12 | mediaType: application/vnd.case.resource.k8s.v1+yaml 13 | - ref: etcd-resources/etcd-operator-psp.yaml 14 | mediaType: application/vnd.case.resource.k8s.v1+yaml 15 | - ref: etcd-resources/etcd-operator-scc.yaml 16 | mediaType: application/vnd.case.resource.k8s.v1+yaml 17 | - ref: etcd-resources/etcdbackups-crd.yaml 18 | mediaType: application/vnd.case.resource.k8s.v1+yaml 19 | - ref: etcd-resources/etcdclusters-crd.yaml 20 | mediaType: application/vnd.case.resource.k8s.v1+yaml 21 | - ref: etcd-resources/etcdrestores-crd.yaml 22 | mediaType: application/vnd.case.resource.k8s.v1+yaml 23 | - ref: install.sh 24 | mediaType: application/vnd.case.resource.script.bash.v1+launcher 25 | 26 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdBackupExample/README.md: -------------------------------------------------------------------------------- 1 | # etcd Backup Exaample 2 | This readme provides instructions on installing the etcdBackup custom resource 3 | 4 | ## Prerequisites 5 | A Kubernetes cluster with the etcd Operator installed, an etcd cluster created, and the etcdBackup Custom Resource Definition created. 6 | 7 | ## Installation 8 | ### Roles required 9 | - Etcd Administrator 10 | 11 | ### Steps 12 | 1. Complete the parameters in `files/etcdBackupExample.yaml` 13 | 1. Login to kubectl as an etcd administrator. 14 | 1. `kubectl apply -f files/etcdBackupExample.yaml` 15 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdBackupExample/actions.yaml: -------------------------------------------------------------------------------- 1 | actions: 2 | actionDefs: 3 | create: 4 | roles: 5 | - etcdAdmin 6 | 7 | # Requires the prerequisite Kubernetes version, amd64 Linux operating system, and the etcdBackup CRD to be installed 8 | requires: 9 | and: 10 | - "/case/prereqs/k8sDistros/kubernetes" 11 | - "/case/prereqs/k8sResources/workerIntelLinux" 12 | - "/case/prereqs/k8sResourceVersions/etcdBackup" 13 | 14 | k8sPermissions: 15 | rules: 16 | - rule: 17 | group: etcd.database.coreos.com 18 | resource: EtcdBackup 19 | verbs: 20 | - get 21 | - list 22 | - watch 23 | - create 24 | - patch 25 | - update 26 | 27 | remove: 28 | roles: 29 | - etcdAdmin 30 | 31 | requires: 32 | and: 33 | - "/case/prereqs/k8sDistros/kubernetes" 34 | - "/case/prereqs/k8sResources/workerIntelLinux" 35 | - "/case/prereqs/k8sResourceVersions/etcdBackup" 36 | 37 | k8sPermissions: 38 | rules: 39 | - rule: 40 | group: etcd.database.coreos.com 41 | resource: EtcdBackup 42 | verbs: 43 | - '*' 44 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdBackupExample/files/etcdBackupExample.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: "etcd.database.coreos.com/v1beta2" 2 | kind: "EtcdBackup" 3 | metadata: 4 | name: etcdBackupExample 5 | spec: 6 | etcdEndpoints: [] 7 | storageType: S3 8 | s3: 9 | # The format of "path" must be: "/" 10 | # e.g: "mybucket/etcd.backup" 11 | path: 12 | awsSecret: -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdBackupExample/inventory.yaml: -------------------------------------------------------------------------------- 1 | inventory: 2 | metadata: 3 | name: etcdBackupExample 4 | description: Backup an etcd cluster 5 | k8sScope: namespace 6 | 7 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdBackupExample/resources.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | metadata: 3 | name: etcdBackupExample 4 | displayName: etcd Resources 5 | displayDescription: etcd Resources that require a cluster admin to create. 6 | resourceDefs: 7 | files: 8 | - ref: etcdBackupExample.yaml 9 | mediaType: application/vnd.case.resource.k8s.v1+yaml 10 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdClusterExample/README.md: -------------------------------------------------------------------------------- 1 | # etcd Cluster Exaample 2 | This readme provides instructions on installing the etcdCluster custom resource 3 | 4 | ## Prerequisites 5 | A Kubernetes cluster with the the etcd Operator installed, including the etcdCluster Custom Resource Definition. 6 | 7 | ## Installation 8 | ### Roles required 9 | - Etcd Administrator 10 | 11 | ### Steps 12 | 1. Complete the parameters in `files/etcdClusterExample.yaml` 13 | 1. Login to kubectl as an etcd administrator. 14 | 1. `kubectl apply -f files/etcdClusterExample.yaml` 15 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdClusterExample/actions.yaml: -------------------------------------------------------------------------------- 1 | actions: 2 | metadata: 3 | name: etcdClusterExample 4 | description: The actions required to create the etcd cluster resources 5 | actionDefs: 6 | create: 7 | roles: 8 | - etcdAdmin 9 | 10 | # Requires the prerequisite Kubernetes version, amd64 Linux operating system, and the etcdCluster CRD to be installed 11 | requires: 12 | and: 13 | - "/case/prereqs/k8sDistros/kubernetes" 14 | - "/case/prereqs/k8sResources/workerIntelLinux" 15 | - "/case/prereqs/k8sResourceVersions/etcdCluster" 16 | 17 | k8sPermissions: 18 | rules: 19 | - rule: 20 | group: etcd.database.coreos.com 21 | resource: EtcdCluster 22 | verbs: 23 | - '*' 24 | 25 | remove: 26 | roles: 27 | - etcdAdmin 28 | 29 | requires: 30 | and: 31 | - "/case/prereqs/k8sDistros/kubernetes" 32 | - "/case/prereqs/k8sResources/workerIntelLinux" 33 | - "/case/prereqs/k8sResourceVersions/etcdBackup" 34 | 35 | k8sPermissions: 36 | rules: 37 | - rule: 38 | group: etcd.database.coreos.com 39 | resource: EtcdCluster 40 | verbs: 41 | - '*' 42 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdClusterExample/files/etcdClusterExample.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: "etcd.database.coreos.com/v1beta2" 2 | kind: "EtcdCluster" 3 | metadata: 4 | name: "etcdClusterExample" 5 | ## Adding this annotation make this cluster managed by clusterwide operators 6 | ## namespaced operators ignore it 7 | # annotations: 8 | # etcd.database.coreos.com/scope: clusterwide 9 | spec: 10 | size: 3 11 | version: "3.2.13" -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdClusterExample/inventory.yaml: -------------------------------------------------------------------------------- 1 | inventory: 2 | metadata: 3 | name: etcdClusterExample 4 | description: Create an etcd cluster 5 | k8sScope: namespace 6 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdClusterExample/resources.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | metadata: 3 | name: etcdClusterExample 4 | displayName: etcd Resources 5 | displayDescription: etcd Resources that require a cluster admin to create. 6 | resourceDefs: 7 | files: 8 | - ref: etcdClusterExample.yaml 9 | mediaType: application/vnd.case.resource.k8s.v1+yaml 10 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdOLMOperators/actions.yaml: -------------------------------------------------------------------------------- 1 | 2 | actions: 3 | metadata: 4 | name: etcdOLMOperators 5 | description: etcd OLM Operator Actions 6 | displayName: etcd OLM Operator Actions 7 | displayDescription: etcd Operator Actions 8 | actionDefs: 9 | install: 10 | metadata : 11 | name: install 12 | displayName: Install the etcd operator catalog 13 | displayDescription: Install the etcd Operator controller Pods and associated custom resource definitions 14 | roles: 15 | - clusterAdmin 16 | requires: 17 | and: 18 | - "/case/prereqs/k8sDistros/kubernetes" 19 | - "/case/prereqs/k8sResourceVersions/rbac" 20 | - "/case/prereqs/k8sResources/workerIntelLinux" 21 | - or: 22 | - and: 23 | - "!": 24 | - "/case/prereqs/k8sDistros/openshift" 25 | - or: 26 | - "/case/prereqs/k8sResources/ibmRestrictedPSP" 27 | - "/case/prereqs/k8sResources/etcdControllerPSP" 28 | - and: 29 | - "/case/prereqs/k8sDistros/openshift" 30 | - or: 31 | - "/case/prereqs/k8sResources/ibmRestrictedSCC" 32 | - "/case/prereqs/k8sResources/etcdControllerSCC" 33 | k8sPermissions: 34 | rules: 35 | - rule: 36 | group: etcd.database.coreos.com 37 | resource: '*' 38 | verbs: 39 | - get 40 | - list 41 | - watch 42 | - create 43 | - patch 44 | - update 45 | remove: 46 | metadata : 47 | name: remove 48 | displayName: Remove 49 | displayDescription: Remove the etcd operator and all etcd databases 50 | roles: 51 | - namespaceAdmin 52 | k8sPermissions: 53 | rules: 54 | - rule: 55 | group: etcd.database.coreos.com 56 | resource: '*' 57 | verbs: 58 | - '*' 59 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdOLMOperators/files/catalogsource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: CatalogSource 3 | metadata: 4 | name: etcd-operator-catalog 5 | spec: 6 | sourceType: grpc 7 | image: coreos/etcd-operator-catalog:latest 8 | imagePullPolicy: Always 9 | displayName: etcd operator 10 | publisher: IBM -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdOLMOperators/files/etcd-cluster-subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: etcd 5 | namespace: openshift-operators 6 | spec: 7 | channel: clusterwide-alpha 8 | name: etcd 9 | source: etcd-operator-catalog 10 | sourceNamespace: openshift-marketplace 11 | installPlanApproval: Automatic 12 | startingCSV: etcdoperator.v0.9.4-clusterwide -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdOLMOperators/inventory.yaml: -------------------------------------------------------------------------------- 1 | inventory: 2 | # This is the main Operator runtime, which includes cluster-scoped operator. 3 | metadata: 4 | name: etcdOperators 5 | displayName: etcd Operators 6 | displayDescription: Install the etcd operator via OLM 7 | k8sScope: cluster 8 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdOLMOperators/resources.yaml: -------------------------------------------------------------------------------- 1 | 2 | resources: 3 | metadata: 4 | name: etcdOperators 5 | displayName: etcd Resources 6 | displayDescription: etcd Resources that require a cluster admin to create. 7 | resourceDefs: 8 | containerImages: 9 | # The Catalog Image that the customer consumes for air-gap 10 | # This is the ENTIRE graph for an operator package. 11 | # Either the workload can create this, or the CICD pipeline can create it. 12 | # This is a catalog that is used for mirroring/air-gap 13 | # There can only be one of these (one per CASE) 14 | - metadata: 15 | description: "The latest etcd operator catalog index" 16 | operators_operatorframework_io: 17 | catalog: # There can only be one of these per CASE 18 | # The the version of the catalog index image type. There is only one currently. 19 | mediaType: "registry+v1" 20 | image: coreos/etcd-operator-catalog 21 | mediaType: application/vnd.oci.image.manifest.v1 22 | tag: latest 23 | platform: 24 | architecture: amd64 25 | os: linux 26 | registries: 27 | - host: quay.io 28 | 29 | # All of the OLM bundle images are included here. 30 | # The CICD will use these bundle images to create the various catalogs. 31 | - metadata: 32 | description: "Obsolete by patch." 33 | operators_operatorframework_io: 34 | bundle: 35 | # The the version of the bundle image type. There is only one currently. 36 | mediaType: "registry+v1" 37 | cpcicd_ibm_com: 38 | targetCatalogs: 39 | catalogRefs: 40 | # The CICD knows this means the IBM PublicCurated Catalog 41 | - ibm-public: {} 42 | 43 | image: coreos/etcd-operator-bundle 44 | mediaType: application/vnd.oci.image.manifest.v1 45 | digest: sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b 46 | tag: v0.9.1 47 | platform: 48 | architecture: amd64 49 | os: linux 50 | registries: 51 | - host: quay.io 52 | 53 | - metadata: 54 | description: "New patch, supercedes 1.9.1" 55 | operators_operatorframework_io: 56 | bundle: 57 | mediaType: "registry+v1" 58 | cpcicd_ibm_com: 59 | targetCatalogs: 60 | catalogRefs: 61 | - ibm-public: {} 62 | image: coreos/etcd-operator-bundle 63 | mediaType: application/vnd.oci.image.manifest.v1 64 | digest: sha256:77a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b 65 | tag: v0.9.2 66 | platform: 67 | architecture: amd64 68 | os: linux 69 | registries: 70 | - host: quay.io 71 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdOperators/actions.yaml: -------------------------------------------------------------------------------- 1 | 2 | actions: 3 | metadata: 4 | name: etcdOperators 5 | description: etcd Operator Actions 6 | displayName: etcd Operator Actions 7 | displayDescription: etcd Operator Actions 8 | actionDefs: 9 | installAll: 10 | metadata : 11 | name: installAll 12 | displayName: Install All 13 | displayDescription: Install the etcd Operator controller Pods and associated custom resource definitions 14 | roles: 15 | - clusterAdmin 16 | requires: 17 | and: 18 | - "/case/prereqs/helm/helmV2" 19 | - "/case/prereqs/k8sDistros/kubernetes" 20 | - "/case/prereqs/k8sResourceVersions/rbac" 21 | - "/case/prereqs/k8sResources/workerIntelLinux" 22 | - or: 23 | - and: 24 | - "!": 25 | - "/case/prereqs/k8sDistros/openshift" 26 | - or: 27 | - "/case/prereqs/k8sResources/ibmRestrictedPSP" 28 | - "/case/prereqs/k8sResources/etcdControllerPSP" 29 | - and: 30 | - "/case/prereqs/k8sDistros/openshift" 31 | - or: 32 | - "/case/prereqs/k8sResources/ibmRestrictedSCC" 33 | - "/case/prereqs/k8sResources/etcdControllerSCC" 34 | k8sPermissions: 35 | rules: 36 | - rule: 37 | group: etcd.database.coreos.com 38 | resource: '*' 39 | verbs: 40 | - get 41 | - list 42 | - watch 43 | - create 44 | - patch 45 | - update 46 | 47 | install: 48 | metadata : 49 | name: install 50 | displayName: Install 51 | displayDescription: Install the etcd Operator controller Pods 52 | roles: 53 | - namespaceAdmin 54 | requires: 55 | and: 56 | - "/case/prereqs/helm/helmV2" 57 | - "/case/prereqs/client/helmClient" 58 | - "/case/prereqs/k8sDistros/kubernetes" 59 | - "/case/prereqs/k8sResources/workerIntelLinux" 60 | - "/case/prereqs/k8sResourceVersions/etcdCluster" 61 | - "/case/prereqs/k8sResourceVersions/etcdBackup" 62 | - "/case/prereqs/k8sResourceVersions/etcdRestore" 63 | - or: 64 | - and: 65 | - "!": 66 | - "/case/prereqs/k8sDistros/openshift" 67 | - or: 68 | - "/case/prereqs/k8sResources/ibmRestrictedPSP" 69 | - "/case/prereqs/k8sResources/etcdControllerPSP" 70 | - and: 71 | - "/case/prereqs/k8sDistros/openshift" 72 | - or: 73 | - "/case/prereqs/k8sResources/ibmRestrictedSCC" 74 | - "/case/prereqs/k8sResources/etcdControllerSCC" 75 | k8sPermissions: 76 | rules: 77 | - rule: 78 | group: etcd.database.coreos.com 79 | resource: '*' 80 | verbs: 81 | - get 82 | - list 83 | - watch 84 | - create 85 | - patch 86 | - update 87 | 88 | remove: 89 | metadata : 90 | name: remove 91 | displayName: Remove 92 | displayDescription: Remove the etcd operator and all etcd databases 93 | roles: 94 | - namespaceAdmin 95 | k8sPermissions: 96 | rules: 97 | - rule: 98 | group: etcd.database.coreos.com 99 | resource: '*' 100 | verbs: 101 | - '*' 102 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdOperators/inventory.yaml: -------------------------------------------------------------------------------- 1 | inventory: 2 | # This is the main Operator runtime, which includes namespace-scoped operator. 3 | metadata: 4 | name: etcdOperators 5 | displayName: etcd Operators 6 | displayDescription: Install the etcd operator Helm Chart 7 | k8sScope: namespace 8 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdOperators/resources.yaml: -------------------------------------------------------------------------------- 1 | 2 | resources: 3 | metadata: 4 | name: etcdOperators 5 | displayName: etcd Resources 6 | displayDescription: etcd Resources that require a cluster admin to create. 7 | resourceDefs: 8 | helmCharts: 9 | - metadata: 10 | name: etcdOperatorChart 11 | displayName: CoreOS etcd-operator Helm chart for Kubernetes 12 | chart: etcd-operator 13 | version: 0.10.2 14 | mediaType: application/vnd.case.resource.helm.chart.v1 15 | repositoryURLs: 16 | - https://kubernetes-charts.storage.googleapis.com 17 | containerImages: 18 | - image: coreos/etcd-operator 19 | mediaType: application/vnd.oci.image.manifest.v1 20 | digest: sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b 21 | tag: v0.9.4 22 | platform: 23 | architecture: amd64 24 | os: linux 25 | registries: 26 | - host: quay.io 27 | - image: coreos/etcd 28 | mediaType: application/vnd.oci.image.manifest.v1 29 | digest: sha256:06520f89439cb7edf4fb921f90e2b4494db3cc5bb61969078dc3e375602a047b 30 | tag: v3.2.25 31 | platform: 32 | architecture: amd64 33 | os: linux 34 | registries: 35 | - host: quay.io -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdRestoreExample/README.md: -------------------------------------------------------------------------------- 1 | # etcd Backup Exaample 2 | This readme provides instructions on installing the etcdRestore custom resource 3 | 4 | ## Prerequisites 5 | A Kubernetes cluster with the etcd Operator installed, an etcd backup created, and the etcdRestore Custom Resource Definition created. 6 | 7 | ## Installation 8 | ### Roles required 9 | - Etcd Administrator 10 | 11 | ### Steps 12 | 1. Complete the parameters in `files/etcdRestoreExample.yaml` 13 | 1. Login to kubectl as an etcd administrator. 14 | 1. `kubectl apply -f files/etcdRestoreExample.yaml` 15 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdRestoreExample/actions.yaml: -------------------------------------------------------------------------------- 1 | actions: 2 | actionDefs: 3 | create: 4 | roles: 5 | - etcdAdmin 6 | 7 | # Requires the prerequisite Kubernetes version, amd64 Linux operating system, and the etcdRestore CRD to be installed 8 | requires: 9 | and: 10 | - "/case/prereqs/k8sDistros/kubernetes" 11 | - "/case/prereqs/k8sResources/workerIntelLinux" 12 | - "/case/prereqs/k8sResourceVersions/etcdRestore" 13 | 14 | k8sPermissions: 15 | rules: 16 | - rule: 17 | group: etcd.database.coreos.com 18 | resource: EtcdRestore 19 | verbs: 20 | - 'get' 21 | - 'list' 22 | - 'create' 23 | remove: 24 | roles: 25 | - etcdAdmin 26 | 27 | requires: 28 | and: 29 | - "/case/prereqs/k8sDistros/kubernetes" 30 | - "/case/prereqs/k8sResources/workerIntelLinux" 31 | - "/case/prereqs/k8sResourceVersions/etcdRestore" 32 | 33 | k8sPermissions: 34 | rules: 35 | - rule: 36 | group: etcd.database.coreos.com 37 | resource: EtcdRestore 38 | verbs: 39 | - '*' -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdRestoreExample/files/etcdRestoreExample.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: "etcd.database.coreos.com/v1beta2" 2 | kind: "EtcdRestore" 3 | metadata: 4 | # The restore CR name must be the same as spec.etcdCluster.name 5 | name: etcdClusterExample 6 | spec: 7 | etcdCluster: 8 | # The namespace is the same as this EtcdRestore CR 9 | name: etcdClusterExample 10 | backupStorageType: S3 11 | s3: 12 | # The format of "path" must be: "/" 13 | # e.g: "mybucket/etcd.backup" 14 | path: 15 | awsSecret: -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdRestoreExample/inventory.yaml: -------------------------------------------------------------------------------- 1 | inventory: 2 | metadata: 3 | name: etcdRestoreExample 4 | description: Setup any namespace requirements 5 | k8sScope: namespace 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/etcdRestoreExample/resources.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | resourceDefs: 3 | files: 4 | - ref: etcdRestoreExample.yaml 5 | mediaType: application/vnd.case.resource.k8s.v1+yaml 6 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/loadAirgapResources/README.md: -------------------------------------------------------------------------------- 1 | # Load the Airgap Archive 2 | 3 | This inventory item provides example scripting and case launch actions to load the images from the airgap archive to a bastion server (or boot stick). This data can then be transfered to within the network, and the install action can be launched to deploy the product. The installer can be ran using the `cloudctl case launch` command. The launch install script takes the following parameters that must be passed in via the `--args` flag in the `cloudctl case launch` command (note the args are a comma separated value list of arg=value format): 4 | 5 | | arg name | type | description | required | 6 | |----------|------|-------------|----------| 7 | | imagesFile | string | file path to the downloaded CASE archive images csv file | yes (if caseArchiveDir is not specified) | 8 | | toRegistry | string | name of the registry the images are to be saved to | yes | 9 | | caseArchiveDir | string | file path to the downloaded CASE archive directory | yes | 10 | 11 | This is the first step in the installation process, and should be ran before `clusterSetup` and `productInstall` launcher actions are executed. 12 | 13 | ## Prereqs 14 | 15 | 1. Docker must be configured to use the default credentials store (docker configuration json) 16 | 1. `docker login` must be performed in order to properly transfer images from registries 17 | 18 | ## Sample Command 19 | 20 | ```raw 21 | $ cloudctl case launch -c \ 22 | --namespace install-namespace \ 23 | --instance demo \ 24 | --inventory loadAirgapResources \ 25 | --action ocMirror \ 26 | --args "imagesFile='case-archive-dir/case-images.csv',imageRegisry=quay.io" 27 | ``` 28 | 29 | ```raw 30 | $ cloudctl case launch -c \ 31 | --namespace install-namespace \ 32 | --instance demo \ 33 | --inventory loadAirgapResources \ 34 | --action ocMirror \ 35 | --args "toRegistry='case-archive-dir',imageRegisry=quay.io" 36 | ``` -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/loadAirgapResources/actions.yaml: -------------------------------------------------------------------------------- 1 | actions: 2 | actionDefs: 3 | dockerPull: 4 | metadata: 5 | name: "dockerPull" 6 | description: "Pulls the images in the CSV file to a local registry" 7 | case.launcher.type: "script" 8 | 9 | roles: 10 | - clusterAdmin 11 | 12 | requires: "/case/prereqs/client/docker" 13 | 14 | k8sPermissions: 15 | rules: [] 16 | 17 | ocMirror: 18 | metadata: 19 | name: "ocMirror" 20 | description: "Mirrors the images to a local registry using oc" 21 | case.launcher.type: "script" 22 | roles: 23 | - clusterAdmin 24 | 25 | requires: "/case/prereqs/client/oc" 26 | 27 | k8sPermissions: 28 | rules: [] 29 | 30 | skopeoCopy: 31 | metadata: 32 | name: "skopeoCopy" 33 | description: "Copies the images from one repo to another using skope" 34 | case.launcher.type: "script" 35 | roles: 36 | - clusterAdmin 37 | 38 | requires: "/case/prereqs/client/skopeo" 39 | 40 | k8sPermissions: 41 | rules: [] -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/loadAirgapResources/files/parse_csv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Default arg values 4 | CASE_ARCHIVE_DIR="" 5 | CSV_FILE="" 6 | ACTION="" 7 | TO_REGISTRY="" 8 | USAGE=" 9 | parse_csv.sh --args \"--imagesFile --toRegistry ,[--caseArchiveDir ]\" 10 | " 11 | 12 | OC_TXT_MAP=$(mktemp /tmp/oc_image_mirror_mapping.XXXXXXXXX) 13 | 14 | # 15 | # ENUM for csv field locations 16 | # 17 | registry=0 18 | image_name=1 19 | tag=2 20 | digest=3 21 | mytype=4 22 | os=5 23 | arch=6 24 | variant=7 25 | insecure=8 26 | 27 | # 28 | # parse_args will parse the CLI args passed to the script 29 | # and set the required internal variables needed. 30 | # 31 | parse_args() { 32 | # Parse CLI parameters 33 | while [ "$1" != "" ]; do 34 | case $1 in 35 | --casePath ) 36 | shift 37 | ;; 38 | --instance ) 39 | shift 40 | ;; 41 | --namespace ) 42 | shift 43 | ;; 44 | --caseJsonFile ) 45 | shift 46 | ;; 47 | --inventory ) 48 | shift 49 | ;; 50 | --action ) 51 | shift 52 | ACTION="${1}" 53 | ;; 54 | --args ) 55 | shift 56 | parse_dynamic_args "${1}" 57 | ;; 58 | *) 59 | echo "Invalid Option ${1}" >&2 60 | exit 1 61 | ;; 62 | 63 | esac 64 | shift 65 | done 66 | } 67 | 68 | # 69 | # Parses the args (--args) parameter if specified. Updates installType if specified. 70 | parse_dynamic_args() { 71 | _IFS=$IFS 72 | IFS=" " 73 | read -ra arr <<< "${1}" 74 | IFS="$_IFS" 75 | arr+=("") 76 | idx=0 77 | v="${arr[${idx}]}" 78 | 79 | while [ "$v" != "" ]; do 80 | case $v in 81 | --imagesFile) 82 | idx=$(( idx + 1 )) 83 | v="${arr[${idx}]}" 84 | CSV_FILE="${v}" 85 | ;; 86 | --toRegistry) 87 | idx=$(( idx + 1 )) 88 | v="${arr[${idx}]}" 89 | TO_REGISTRY="${v}" 90 | ;; 91 | --caseArchiveDir) 92 | idx=$(( idx + 1 )) 93 | v="${arr[${idx}]}" 94 | CASE_ARCHIVE_DIR="${v}" 95 | ;; 96 | --help) 97 | print_usage 0 98 | ;; 99 | *) 100 | echo "Invalid Option ${v}" >&2 101 | exit 1 102 | ;; 103 | esac 104 | idx=$(( idx + 1 )) 105 | v="${arr[${idx}]}" 106 | done 107 | } 108 | 109 | # 110 | # print_usage prints usage menu and exits with $1 111 | # 112 | print_usage() { 113 | echo "[ Usage: ${USAGE}" 114 | exit "${1}" 115 | } 116 | 117 | # 118 | # parse_case_image_csv turns the image CSV file into newline separated array 119 | # held in memory to be used by other functions later. 120 | # 121 | IMAGE_CSV_MEMORY_ARRAY= 122 | parse_case_image_csv() { 123 | _IFS=$IFS 124 | IFS=$'\r\n' 125 | IMAGE_CSV_MEMORY_ARRAY=($(cat "${CSV_FILE}")) 126 | IFS=$_IFS 127 | } 128 | 129 | # 130 | # parse_case_image_csv_for_field example function for how to parse all fields of 131 | # the CSV file out 132 | # 133 | parse_case_image_csv_for_field() { 134 | _IFS=$IFS 135 | field="${1}" 136 | 137 | if [[ -z "${field}" ]]; then field="${registry}"; fi 138 | 139 | idx=1 140 | while [[ idx -ne ${#IMAGE_CSV_MEMORY_ARRAY[@]} ]]; do 141 | line=${IMAGE_CSV_MEMORY_ARRAY[${idx}]} 142 | IFS=',' 143 | read -ra split_line <<< "${line}" 144 | echo ${split_line[${field}]} 145 | 146 | idx=$(( idx + 1 )) 147 | done 148 | IFS=$_IFS 149 | } 150 | 151 | # 152 | # parse_case_image_csv_for_field_with_index example function for how to get a specific 153 | # field from a specific line in the CSV 154 | # 155 | parse_case_image_csv_for_field_with_index() { 156 | field="${1}" 157 | idx="${2}" 158 | 159 | if [[ -z "${field}" ]]; then field="${registry}"; fi 160 | if [[ -z "${idx}" ]]; then idx=0; fi 161 | 162 | line=${IMAGE_CSV_MEMORY_ARRAY[${idx}]} 163 | _IFS=$IFS 164 | IFS=',' 165 | read -ra split_line <<< "${line}" 166 | echo ${split_line[${field}]} 167 | IFS=$_IFS 168 | } 169 | 170 | # 171 | # example_download_using_docker will download all the images in the CSV using 172 | # docker and your local docker config. 173 | # 174 | example_download_using_docker() { 175 | len=${#IMAGE_CSV_MEMORY_ARRAY[@]} 176 | idx=0 177 | _IFS=$IFS 178 | IFS=':' 179 | read -ra split_creds <<< "${SOURCE_REPOSITORY_CREDENTIALS}" 180 | 181 | docker_u="${split_creds[0]}" 182 | docker_p="${split_creds[1]}" 183 | 184 | # Any other docker config info will go here as well 185 | 186 | docker login -u "$docker_u" -p "$docker_p" 187 | 188 | while [[ idx -ne len ]] 189 | do 190 | line=${IMAGE_CSV_MEMORY_ARRAY[${idx}]} 191 | IFS=',' 192 | read -ra split_line <<< "${line}" 193 | 194 | source_registry="${split_line[${registry}]}" 195 | source_image_name="${split_line[${image_name}]}" 196 | source_tag="${split_line[${tag}]}" 197 | source_arch="${split_line[${arch}]}" 198 | source_digest="${split_line[${digest}]}" # Optional 199 | 200 | if [[ -z "$source_digest" ]] 201 | then 202 | docker pull "${source_registry}/${source_image_name}@${source_digest}" 203 | else 204 | docker pull "${source_registry}/${source_image_name}:${source_tag}" 205 | fi 206 | 207 | idx=$(( idx + 1 )) 208 | done 209 | IFS=$_IFS 210 | } 211 | 212 | # 213 | # example_oc_image_mirror will mirror images in the CSV file to a hosted 214 | # registry, using oc mirror image command 215 | # 216 | example_oc_image_mirror() { 217 | _IFS=$IFS 218 | len=${#IMAGE_CSV_MEMORY_ARRAY[@]} 219 | idx=1 220 | 221 | while [[ idx -ne len ]] 222 | do 223 | line=${IMAGE_CSV_MEMORY_ARRAY[${idx}]} 224 | IFS=',' 225 | read -ra split_line <<< "${line}" 226 | 227 | source_registry="${split_line[${registry}]}" 228 | source_image_name="${split_line[${image_name}]}" 229 | source_tag="${split_line[${tag}]}" 230 | source_arch="${split_line[${arch}]}" 231 | source_digest="${split_line[${digest}]}" 232 | 233 | dest_string="${TO_REGISTRY}/${source_image_name}:${source_tag}" 234 | 235 | echo "${source_registry}/${source_image_name}@${source_digest}=$dest_string" >> "$OC_TXT_MAP" 236 | 237 | idx=$(( idx + 1 )) 238 | done 239 | IFS=$_IFS 240 | } 241 | 242 | # 243 | # example_skopeo will copy images in the CSV file to a hosted 244 | # registry, using skopeo copy command 245 | # 246 | example_skopeo() { 247 | _IFS=$IFS 248 | len=${#IMAGE_CSV_MEMORY_ARRAY[@]} 249 | idx=1 250 | s_rc=0 251 | 252 | while [[ idx -ne len ]] 253 | do 254 | line=${IMAGE_CSV_MEMORY_ARRAY[${idx}]} 255 | IFS=',' 256 | read -ra split_line <<< "${line}" 257 | 258 | source_registry="${split_line[${registry}]}" 259 | source_image_name="${split_line[${image_name}]}" 260 | source_tag="${split_line[${tag}]}" 261 | source_arch="${split_line[${arch}]}" 262 | source_digest="${split_line[${digest}]}" 263 | 264 | dest_string="docker://${TO_REGISTRY}/${source_image_name}:${source_tag}" 265 | 266 | skopeo copy \ 267 | "docker://${source_registry}/${source_image_name}@${source_digest}" \ 268 | "$dest_string" \ 269 | "--all" 270 | 271 | if [[ "$rc" -ne 0 ]]; then 272 | s_rc=11 273 | fi 274 | 275 | idx=$(( idx + 1 )) 276 | done 277 | IFS=$_IFS 278 | return s_rc 279 | } 280 | 281 | # 282 | # example_parse_all_oc_image_mirror is an example of parsing the image 283 | # CSV and using oc mirror to transfer the images to an internal repository 284 | # 285 | example_parse_all_oc_image_mirror() { 286 | touch "$OC_TXT_MAP" 287 | 288 | if [[ -z "${CSV_FILE}" ]] 289 | then 290 | for fname in ${CASE_ARCHIVE_DIR}/*-images.csv; do 291 | CSV_FILE="$fname" 292 | parse_case_image_csv 293 | example_oc_image_mirror 294 | done 295 | else 296 | parse_case_image_csv 297 | example_oc_image_mirror 298 | fi 299 | 300 | oc image mirror --filter-by-os '.' -f "$OC_TXT_MAP" --max-per-registry 1 --insecure 301 | o_rc="$?" 302 | rm -f "$OC_TXT_MAP" 303 | if [[ "$o_rc" -ne 0 ]]; then 304 | exit 11 305 | fi 306 | 307 | } 308 | 309 | # 310 | # example_parse_all_skopeo_copy is an example of parsing the image 311 | # CSV and using skopeo copy to transfer the images to an internal repository 312 | # 313 | example_parse_all_skopeo_copy() { 314 | if [[ -z "${CSV_FILE}" ]] 315 | then 316 | for fname in "${CASE_ARCHIVE_DIR}"/*-images.csv; do 317 | CSV_FILE="$fname" 318 | parse_case_image_csv 319 | example_skopeo 320 | rc="$?" 321 | done 322 | else 323 | parse_case_image_csv 324 | example_skopeo 325 | rc="$?" 326 | fi 327 | 328 | if [[ "$rc" -ne 0 ]]; then 329 | exit 11 330 | fi 331 | } 332 | 333 | # 334 | # example_main_entry_point provides an example flow for 335 | # an end to end scenario launched from the CASE launcher 336 | # provided by cloudctl. 337 | # 338 | example_main_entry_point() { 339 | case "$ACTION" in 340 | skopeoCopy) 341 | echo "Using skopeo copy" 342 | example_parse_all_skopeo_copy 343 | ;; 344 | ocMirror) 345 | echo "Using oc image mirror" 346 | example_parse_all_oc_image_mirror 347 | ;; 348 | *) 349 | echo "Action: $ACTION not supported at this time" 350 | ;; 351 | esac 352 | } 353 | 354 | parse_args "$@" 355 | 356 | echo -en "\033[0;36mParsing the image CSV file located at: \033[0m" 357 | if [[ -z "${CSV_FILE}" ]] 358 | then 359 | echo "imagesFile not set, defaulting to all image CSV files" 360 | else 361 | echo "${CSV_FILE}" 362 | fi 363 | 364 | example_main_entry_point -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/loadAirgapResources/inventory.yaml: -------------------------------------------------------------------------------- 1 | inventory: 2 | metadata: 3 | name: loadAirgapResources 4 | description: Load in airgap resources such as images 5 | k8sScope: cluster 6 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/loadAirgapResources/resources.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | resourceDefs: 3 | files: 4 | - ref: parse_csv.sh 5 | mediaType: application/vnd.case.resource.script.bash.v1+launcher 6 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/namespaceSetup/README.md: -------------------------------------------------------------------------------- 1 | # etcd Namespace Setup 2 | This readme provides instructions on how to manually install and configure the Kubernetes cluster to run the etcd Operator. 3 | 4 | ## Prerequisites 5 | 6 | ## Configuration 7 | The following items need to be performed manually: 8 | 1. Create a namespace. 9 | 2. (Optional) Create or choose a Kubernetes user or group to administer the etcd cluster (the etcdAdministrator role) 10 | 3. (Optional) Create a RoleBinding to bind the etcd user to the the `etcd-operator` ClusterRole 11 | 4. (Optional) Create a NetworkPolicy 12 | 5. (Optional) Create a ServiceAccount 13 | 6. (Optional) Bind the ServiceAccount to the `ibm-restricted-psp` PodSecurityPolicy or `restricted` SecurityContextConstraint (OpenShift) 14 | 15 | ## Removal 16 | To remove this configuration 17 | 1. `kubectl delete ns ` 18 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/namespaceSetup/actions.yaml: -------------------------------------------------------------------------------- 1 | 2 | actions: 3 | metadata: 4 | name: namespaceSetup 5 | description: Setup any namespace requirements 6 | 7 | actionDefs: 8 | configure: 9 | metadata : 10 | name: configure 11 | description: Setup the namespace 12 | roles: 13 | - namespaceAdmin 14 | 15 | # Requires the prerequisite Kubernetes version and the amd64 Linux operating system 16 | requires: 17 | and: 18 | - "/case/prereqs/k8sDistros/kubernetes" 19 | - "/case/prereqs/k8sResources/workerIntelLinux" 20 | - or: 21 | - and: 22 | - "!": 23 | - "/case/prereqs/k8sDistros/openshift" 24 | - or: 25 | - "/case/prereqs/k8sResources/ibmRestrictedPSP" 26 | - "/case/prereqs/k8sResources/etcdControllerPSP" 27 | - "/case/prereqs/k8sResources/pspClusterRole" 28 | - and: 29 | - "/case/prereqs/k8sDistros/openshift" 30 | - or: 31 | - "/case/prereqs/k8sResources/ibmRestrictedSCC" 32 | - "/case/prereqs/k8sResources/etcdControllerSCC" 33 | 34 | k8sPermissions: 35 | rules: 36 | - rule: 37 | group: "" 38 | resource: "namespaces" 39 | verbs: 40 | - get 41 | - list 42 | - watch 43 | - create 44 | - patch 45 | - update 46 | - rule: 47 | group: "extensions" 48 | resource: "networkpolicies" 49 | verbs: 50 | - get 51 | - list 52 | - watch 53 | - create 54 | - patch 55 | - update 56 | - rule: 57 | group: "" 58 | resource: "serviceaccounts" 59 | verbs: 60 | - get 61 | - list 62 | - watch 63 | - create 64 | - patch 65 | - update 66 | remove: 67 | metadata : 68 | name: remove 69 | description: Undo the namespace setup configuration 70 | roles: 71 | - namespaceAdmin 72 | 73 | # Requires the prerequisite Kubernetes version and the amd64 Linux operating system 74 | requires: 75 | and: 76 | - "/case/prereqs/k8sDistros/kubernetes" 77 | - "/case/prereqs/k8sResources/workerIntelLinux" 78 | 79 | k8sPermissions: 80 | rules: 81 | - rule: 82 | group: "" 83 | resource: "namespaces" 84 | verbs: 85 | - '*' 86 | - rule: 87 | group: "extensions" 88 | resource: "networkpolicies" 89 | verbs: 90 | - '*' 91 | - rule: 92 | group: "" 93 | resource: "serviceaccounts" 94 | verbs: 95 | - '*' 96 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/namespaceSetup/files/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | controller-tools.k8s.io: "1.0" 6 | name: -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/namespaceSetup/files/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: psp-binding 5 | namespace: 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: ibm-restricted-psp-etcd-cr 10 | subjects: 11 | - kind: ServiceAccount 12 | name: etcdServiceAccount 13 | namespace: -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/namespaceSetup/files/scc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Use this script to apply the Security Context Constraint (SCC) 4 | # Created in the clusterSetup inventory item 5 | # 6 | 7 | namespace=$1 8 | 9 | if [[ "$#" -ne 1 ]] || [[ -z ${namespace} ]]; then 10 | echo "Usage: ./scc.sh " 11 | exit 1 12 | fi 13 | 14 | oc adm policy add-scc-to-group ibm-restricted-scc-etcd system:serviceaccounts:$namespace -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/namespaceSetup/files/service-account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: etcdServiceAccount 5 | imagePullSecrets: 6 | - name: -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/namespaceSetup/inventory.yaml: -------------------------------------------------------------------------------- 1 | inventory: 2 | metadata: 3 | name: namespaceSetup 4 | description: Setup any namespace requirements 5 | k8sScope: cluster 6 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/namespaceSetup/resources.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | metadata: 3 | name: namespaceSetup 4 | displayName: Namespace Setup 5 | displayDescription: etcd resources that require a namespace admin 6 | resourceDefs: 7 | files: 8 | - ref: namespace.yaml 9 | mediaType: application/vnd.case.resource.k8s.v1+yaml 10 | - ref: rolebinding.yaml 11 | mediaType: application/vnd.case.resource.k8s.v1+yaml 12 | - ref: service-account.yaml 13 | mediaType: application/vnd.case.resource.k8s.v1+yaml 14 | - ref: scc.sh 15 | mediaType: application/vnd.case.resource.script.bash.v1 16 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/productInstall/README.md: -------------------------------------------------------------------------------- 1 | # Install etcd-operator 2 | 3 | This inventory item contains the installer for the CASE. The installer can be ran using the `cloudctl case launch` command. The launch install script takes the following parameters that must be passed in via the `--args` flag in the `cloudctl case launch` command (note the args are a comma separated value list of arg=value format): 4 | 5 | | arg name | type | description | required | 6 | |----------|------|-------------|----------| 7 | | imagePullSecret | string | name of the pull secret used to acces the image registry | yes | 8 | | chartsFile | string | file path to the downloaded CASE archive charts csv file | yes | 9 | | imageRegistry | string | image registry location the images are hosted in | yes | 10 | 11 | This is the last step in the installation process, and should be ran after `loadAirgapResources` and `clusterSetup` launcher actions have been executed. 12 | 13 | ## Sample Command 14 | 15 | ```raw 16 | $ cloudctl case launch -c \ 17 | --namespace install-namespace \ 18 | --instance demo \ 19 | --inventory productInstall \ 20 | --action install \ 21 | --args "imagePullSecret=demo-pull-secret,chartsFile='case-archive-dir/case-charts.csv',imageRegisry=quay.io" 22 | ``` -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/productInstall/actions.yaml: -------------------------------------------------------------------------------- 1 | actions: 2 | metadata: 3 | name: productInstall 4 | description: The actions required to install the etcd cluster resources 5 | actionDefs: 6 | # Install the product. The sections below constitute the combination of any install actions 7 | # from the other inventory items. 8 | install: 9 | metadata: 10 | name: "install" 11 | description: "Installs the etcd operator" 12 | case.launcher.type: "script" 13 | roles: 14 | - clusterAdmin 15 | 16 | # The system must be Openshift, IBM Cloud, or IBM Cloud Private running on amd64, with 17 | # Helm 2 and Kubernetes installed. 18 | requires: 19 | and: 20 | - "/case/prereqs/k8sDistros/kubernetes" 21 | - "/case/prereqs/k8sResourceVersions/rbac" 22 | - "/case/prereqs/k8sResources/workerIntelLinux" 23 | - or: 24 | - "/case/prereqs/helm/helmV2" 25 | - "/case/prereqs/helm/helmV3" 26 | - or: 27 | - and: 28 | - "!": 29 | - "/case/prereqs/k8sDistros/openshift" 30 | - or: 31 | - "/case/prereqs/k8sResources/ibmRestrictedPSP" 32 | - "/case/prereqs/k8sResources/etcdControllerPSP" 33 | - and: 34 | - "/case/prereqs/k8sDistros/openshift" 35 | - or: 36 | - "/case/prereqs/k8sResources/ibmRestrictedSCC" 37 | - "/case/prereqs/k8sResources/etcdControllerSCC" 38 | 39 | # User must have the ability to create cluster roles, custom resource definitions, namespaces, 40 | # service accounts and network policies 41 | k8sPermissions: 42 | rules: 43 | - rule: 44 | group: rbac.authorization.k8s.io 45 | resource: clusterroles 46 | verbs: 47 | - get 48 | - list 49 | - watch 50 | - create 51 | - patch 52 | - update 53 | version: '*' 54 | - rule: 55 | group: apiextensions.k8s.io 56 | resource: customresourcedefinitions 57 | verbs: 58 | - get 59 | - list 60 | - watch 61 | - create 62 | - patch 63 | - update 64 | version: v1beta1 65 | - rule: 66 | group: "" 67 | resource: "namespaces" 68 | verbs: 69 | - get 70 | - list 71 | - watch 72 | - create 73 | - patch 74 | - update 75 | - rule: 76 | group: "extensions" 77 | resource: "networkpolicies" 78 | verbs: 79 | - get 80 | - list 81 | - watch 82 | - create 83 | - patch 84 | - update 85 | - rule: 86 | group: "" 87 | resource: "serviceaccounts" 88 | verbs: 89 | - get 90 | - list 91 | - watch 92 | - create 93 | - patch 94 | - update 95 | 96 | # Resolve this permission check ONLY if the prereq resolves to true. 97 | - ifExpression: 98 | "!": 99 | - "/case/prereqs/k8sDistros/openshift" 100 | rule: 101 | group: policy 102 | resource: podsecuritypolicies 103 | verbs: 104 | - get 105 | - list 106 | - watch 107 | - create 108 | - patch 109 | - update 110 | 111 | - ifExpression: 112 | "/prereqs/k8sDistros/openshift" 113 | rule: 114 | group: security.openshift.io 115 | resource: securitycontextconstraints 116 | verbs: 117 | - get 118 | - list 119 | - watch 120 | - create 121 | - patch 122 | - update 123 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/productInstall/files/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Installs the ectd-operator-case 5 | # Usage: install.sh [-a args] [-j casejsonpath] [-o operation] [-i instancename] [-n namespace] -c casepath 6 | # 7 | # The additional args parameters include: createNamespace, pullSecretName, chartsFile, imageRegistry 8 | # 9 | 10 | # default values 11 | installType="all" 12 | createNamespace=0 13 | pullSecretName="default" 14 | caseJsonFile="" 15 | casePath="" 16 | inventory="" 17 | action="" 18 | namespace="" 19 | instance="" 20 | args="" 21 | chartsFile="" 22 | imageReg="" 23 | 24 | 25 | print_usage () { 26 | echo "usage: install.sh [--caseJsonFile casejsonpath --inventory inventoryItemOfLauncher --action launchAction] --args \"--createNamespace=true --imagePullSecret=pullSecretName --chartsFile chartsFilePath --imageRegistry internalImageRegistry\" --casePath casepath --instance instancename --namespace namespace" 27 | if [ -z $1 ]; then 28 | exit 1 29 | else 30 | exit $1 31 | fi 32 | } 33 | 34 | # Parses the args (--args) parameter if specified 35 | parse_dynamic_args () { 36 | _IFS=$IFS 37 | IFS=" " 38 | read -ra arr <<< "${1}" 39 | IFS="$_IFS" 40 | arr+=("") 41 | idx=0 42 | v="${arr[${idx}]}" 43 | 44 | while [ "$v" != "" ]; do 45 | case $v in 46 | --createNamespace) 47 | idx=$(( idx + 1 )) 48 | v="${arr[${idx}]}" 49 | if [ "${v}" = "true" ] || [ "${v}" = "1" ]; then 50 | createNamespace=1 51 | fi 52 | ;; 53 | --chartsFile) 54 | idx=$(( idx + 1 )) 55 | v="${arr[${idx}]}" 56 | chartsFile="${v}" 57 | ;; 58 | --imageRegistry) 59 | idx=$(( idx + 1 )) 60 | v="${arr[${idx}]}" 61 | imageReg="${v}" 62 | ;; 63 | --pullSecretName) 64 | idx=$(( idx + 1 )) 65 | v="${arr[${idx}]}" 66 | pullSecretName="${v}" 67 | ;; 68 | --help) 69 | print_usage 0 70 | ;; 71 | *) 72 | echo "Invalid Option ${v}" >&2 73 | exit 1 74 | ;; 75 | esac 76 | idx=$(( idx + 1 )) 77 | v="${arr[${idx}]}" 78 | done 79 | foundError=0 80 | if [ -z $pullSecretName ]; then 81 | echo "Error: The pullSecretName parameter was not specified with the --args parameter." 82 | foundError=1 83 | fi 84 | if [ -z $chartsFile ]; then 85 | echo "Error: The chartsFile parameter was not specified with the --args parameter." 86 | foundError=1 87 | fi 88 | if [ -z $imageReg ]; then 89 | echo "Error: The imageRegistry parameter was not specified with the --args parameter." 90 | foundError=1 91 | fi 92 | if [ $foundError -eq 1 ]; then 93 | print_usage 94 | fi 95 | } 96 | 97 | # Validates that the required parameters were specified 98 | check_cli_args () { 99 | foundError=0 100 | if [ -z $casePath ]; then 101 | echo "Error: The case path parameter was not specified." 102 | foundError=1 103 | else 104 | ls $casePath/case.yaml > /dev/null 105 | if [ $? != 0 ]; then 106 | echo "Error: No case.yaml in the root of the specified case path parameter." 107 | foundError=1 108 | fi 109 | fi 110 | 111 | parse_dynamic_args 112 | 113 | if [ $foundError -eq 1 ]; then 114 | print_usage 115 | fi 116 | } 117 | 118 | # Verifies that we have a connection to the Kubernetes cluster 119 | check_kube_connection () { 120 | kubectl get pods > /dev/null 121 | if [ $? != 0 ]; then 122 | # Developer note: Kubectl should be included in your prereqs.yaml as a client prereq if it is required for your script. 123 | echo "Error executing kubectl. Verify that kubectl is installed and you are connected to a Kubernetes cluster." 124 | exit 1 125 | fi 126 | } 127 | 128 | # Creates the resources specified in the namespaceSetup inventory item. Optionally creates a namespace. 129 | namespace_setup () { 130 | if [ -z $namespace ]; then 131 | echo "Error: The namespace was not specified." 132 | print_usage 133 | fi 134 | if ! kubectl get namespace $namespace ; then 135 | echo "Error: The specified namespace [$namespace] does not exist." 136 | fi 137 | set -e 138 | sed "s//$namespace/g" $casePath/inventory/namespaceSetup/files/rolebinding.yaml | kubectl apply -n $namespace -f - 139 | sed "s//$pullSecretName/g" $casePath/inventory/namespaceSetup/files/service-account.yaml | kubectl apply -n $namespace -f - 140 | $casePath/inventory/namespaceSetup/files/scc.sh $namespace 141 | set +e 142 | } 143 | 144 | # Install the operator from the etcdOperators inventory item 145 | install_operator () { 146 | # Verify that we have the expected parameters specified. 147 | foundError=0 148 | if [ -z $namespace ]; then 149 | echo "Error: The namespace was not specified." 150 | foundError=1 151 | fi 152 | if [ -z $instance ]; then 153 | echo "Error: The instance name was not specified." 154 | foundError=1 155 | fi 156 | if [ $foundError -eq 1 ]; then 157 | print_usage 158 | fi 159 | version=`cat $casePath/inventory/etcdOperators/resources.yaml | grep version | awk -F: {'print $2'}` 160 | set -e 161 | 162 | HELM_CSV_MEMORY_ARRAY=($(cat "${chartsFile}")) 163 | helm_row=${HELM_CSV_MEMORY_ARRAY[1]} 164 | OLDIFS=$IFS 165 | IFS="," 166 | chart_name=`echo "$helm_row" | awk -F, '{print $1}'` 167 | chart_version=`echo "$helm_row" | awk -F, '{print $2}'` 168 | IFS=$OLDIFS 169 | 170 | case_archive_dir="$(dirname ${chartsFile})" 171 | 172 | if helm version | grep "v3\." ; then 173 | echo "Installing etcd-operator chart using Helm 3 syntax" 174 | helm install "${case_archive_dir}/charts/${chart_name}-${chart_version}.tgz" --name-template $instance --namespace $namespace --version $version --set serviceAccount.create=false,serviceAccount.name=etcd-service-account,etcdOperator.image.repository=$imageReg/coreos/etcd-operator,etcdOperator.image.tag=v0.9.4-amd64,backupOperator.image.repository=$imageReg/coreos/etcd-operator,backupOperator.image.tag=v0.9.4-amd64,restoreOperator.image.repository=$imageReg/coreos/etcd-operator,restoreOperator.image.tag=v0.9.4-amd64 175 | else 176 | echo "Installing etcd-operator chart using Helm 2 syntax" 177 | helm install "${case_archive_dir}/charts/${chart_name}-${chart_version}.tgz" --name $instance --namespace $namespace --version $version --set serviceAccount.create=false,serviceAccount.name=etcd-service-account,etcdOperator.image.repository=$imageReg/coreos/etcd-operator,etcdOperator.image.tag=v0.9.4-amd64,backupOperator.image.repository=$imageReg/coreos/etcd-operator,backupOperator.image.tag=v0.9.4-amd64,restoreOperator.image.repository=$imageReg/coreos/etcd-operator,restoreOperator.image.tag=v0.9.4-amd64 --tls 178 | fi 179 | set +e 180 | } 181 | 182 | # Runs the expected commands 183 | run_install () { 184 | echo "Executing installOperator" 185 | check_kube_connection 186 | namespace_setup 187 | install_operator 188 | } 189 | 190 | # Parse CLI parameters 191 | while [ "$1" != "" ]; do 192 | case $1 in 193 | --caseJsonFile ) 194 | shift 195 | caseJsonFile="${1}" 196 | ;; 197 | --casePath ) 198 | shift 199 | casePath="${1}" 200 | ;; 201 | --inventory ) 202 | shift 203 | inventory="${1}" 204 | ;; 205 | --action ) 206 | shift 207 | action="${1}" 208 | ;; 209 | --namespace ) 210 | shift 211 | namespace="${1}" 212 | ;; 213 | --instance ) 214 | shift 215 | instance="${1}" 216 | ;; 217 | --args ) 218 | shift 219 | parse_dynamic_args "${1}" 220 | ;; 221 | --help ) 222 | print_usage 0 223 | ;; 224 | *) 225 | echo "Invalid Option ${1}" >&2 226 | exit 1 227 | ;; 228 | esac 229 | shift 230 | done 231 | 232 | # Execution order 233 | check_cli_args 234 | run_install -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/productInstall/inventory.yaml: -------------------------------------------------------------------------------- 1 | inventory: 2 | # This is the main Operator runtime, which includes namespace-scoped operator. 3 | metadata: 4 | name: productInstall 5 | displayName: Install etcd 6 | displayDescription: Sets up the namespace and installs the etcd Operator 7 | k8sScope: namespace 8 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/inventory/productInstall/resources.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | resourceDefs: 3 | files: 4 | - ref: install.sh 5 | mediaType: application/vnd.case.resource.script.bash.v1+launcher 6 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/prereqs.yaml: -------------------------------------------------------------------------------- 1 | # Defines any external dependencies that are not directly supplied by this CASE 2 | # The dependencies are handled by dependency resolvers which evaluate the prerequiste 3 | # These values can be addressed canonically 4 | prereqs: 5 | prereqDefs: 6 | k8sResources: # Kubernetes resource instance resolver # TODO: Add label queries, namespace 7 | ibmRestrictedPSP: # boolean: true if present and accessible 8 | kind: PodSecurityPolicy 9 | apiGroup: policy 10 | name: ibm-restricted-psp 11 | version: v1beta1 12 | 13 | etcdControllerPSP: 14 | kind: PodSecurityPolicy 15 | apiGroup: policy 16 | name: etcd-contoller-psp 17 | version: v1beta1 18 | 19 | ibmRestrictedSCC: 20 | kind: SecurityContextConstraints 21 | apiGroup: security.openshift.io 22 | name: restricted 23 | version: v1 24 | 25 | etcdControllerSCC: 26 | kind: SecurityContextConstraints 27 | apiGroup: security.openshift.io 28 | name: etcd-contoller-scc 29 | version: v1 30 | 31 | pspClusterRole: 32 | kind: ClusterRole 33 | apiGroup: rbac.authorization.k8s.io 34 | name: ibm-restricted-psp-etcd-cr 35 | version: v1 36 | 37 | workerIntelLinux: 38 | kind: node 39 | apiGroup: "" 40 | version: v1 41 | selector: 42 | matchExpressions: 43 | - {key: beta.kubernetes.io/arch, operator: In, values: [amd64]} 44 | - {key: beta.kubernetes.io/os, operator: In, values: [linux]} 45 | - {key: node-role.kubernetes.io/worker, operator: Exists} 46 | 47 | k8sResourceVersions: # Kubernetes APIs and Resource types. 48 | rbac: # boolean: true if present 49 | kind: ClusterRole 50 | apiGroup: rbac.authorization.k8s.io 51 | version: v1 52 | etcdCluster: 53 | kind: EtcdCluster 54 | apiGroup: etcd.database.coreos.com 55 | version: v1beta2 56 | etcdBackup: 57 | kind: EtcdBackup 58 | apiGroup: etcd.database.coreos.com 59 | version: v1beta2 60 | etcdRestore: 61 | kind: EtcdRestore 62 | apiGroup: etcd.database.coreos.com 63 | version: v1beta2 64 | 65 | k8sDistros: # Kubernetes Distributions resolver 66 | ibmCloud: # boolean: true if present and accessible 67 | distribution: ibmCloud 68 | semver: ">=1.11.3" 69 | ibmCloudPrivate: 70 | distribution: ibmCloudPrivate 71 | semver: ">=1.11.3" 72 | openshift: 73 | distribution: openshift 74 | semver: ">=1.11.3" 75 | kubernetes: 76 | distribution: kubernetes 77 | semver: ">=1.11-0" 78 | 79 | helm: # If this is here at all, it requires the Helm client to be installed. 80 | helmV2: 81 | helmVersion: ">2.12.0" 82 | tillerVersion: ">2.12.0" 83 | helmV3: 84 | helmVersion: ">3.0.0" 85 | 86 | client: 87 | kubectl: 88 | command: "kubectl" 89 | versionArgs: "version" 90 | versionRegex: "GitVersion:\"v1.13.[0-9]*" 91 | docker: 92 | command: "docker" 93 | versionArgs: "--version" 94 | versionRegex: "Docker version 1[8-9].d*.d*,.*" 95 | oc: 96 | command: "oc" 97 | versionArgs: "version" 98 | versionRegex: "((Client Version: openshift-clients-4.[0-9]*.[0-9]*-[0-9a-zA-Z]*-[0-9a-zA-z]*-*)|GitVersion:\"v4.(0|[1-9][0-9]*).(0|[1-9][0-9]*))" 99 | skopeo: 100 | command: "skopeo" 101 | versionArgs: "--version" 102 | versionRegex: "skopeo version 0.1.4[1-9]*" 103 | -------------------------------------------------------------------------------- /samples/etcd-operator-case/roles.yaml: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------- 2 | # Named roles (for documentation and grouping) 3 | # The role keys are used by other resources to describe what role(s) are required 4 | # to interact with that resource given a specific action. 5 | # ---------------------------------------------------------- 6 | roles: 7 | roleDefs: 8 | clusterAdmin: 9 | metadata: 10 | name: clusterAdmin 11 | displayName: Cluster Admin 12 | displayDescription: A user who has cluster administrator permissions. 13 | 14 | namespaceAdmin: 15 | metadata: 16 | name: namespaceAdmin 17 | displayName: Namespace Admin 18 | displayDescription: A user who has namespace administrator permissions. 19 | 20 | etcdAdmin: 21 | metadata: 22 | name: etcdAdmin 23 | displayName: etcd Admin 24 | displayDescription: A user who has the authority to administer etcd cluster instances. 25 | -------------------------------------------------------------------------------- /schema/actions.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 5 | "type": "object", 6 | "title": "Root schema", 7 | "description": "The root of the actions schema", 8 | "required": [ 9 | "actions" 10 | ], 11 | "properties": { 12 | "actions": { 13 | "$id": "#/properties/actions", 14 | "type": "object", 15 | "title": "Actions", 16 | "description": "Contains the action definitions for the inventory item", 17 | "required": [ 18 | "actionDefs" 19 | ], 20 | "properties": { 21 | "metadata": { 22 | "$ref": "metadata.json#/definitions/metadataRef" 23 | }, 24 | "actionDefs": { 25 | "$id": "#/properties/actions/actionDefs", 26 | "type": "object", 27 | "title": "Action definitions", 28 | "description": "Defines the actions for the inventory item.", 29 | "additionalProperties": false, 30 | "patternProperties": { 31 | "^[a-z_$][A-Za-z0-9_$]{0,49}$": { 32 | "type": "object", 33 | "title": "Action", 34 | "description": "Defines an action for the inventory item", 35 | "required": [ 36 | "roles", 37 | "k8sPermissions" 38 | ], 39 | "properties": { 40 | "metadata ": { 41 | "$ref": "metadata.json#/definitions/metadataRef" 42 | }, 43 | "roles": { 44 | "$id": "#/properties/actions/properties/roles", 45 | "type": "array", 46 | "title": "Action roles", 47 | "description": "The CASE roles that apply to this action", 48 | "items": { 49 | "$id": "#/properties/actions/properties/roles/items", 50 | "type": "string", 51 | "title": "Action role schema", 52 | "description": "Describes a CASE role that applies to this action", 53 | "default": "", 54 | "examples": [ 55 | "etcdAdmin" 56 | ], 57 | "pattern": "^(.*)$" 58 | } 59 | }, 60 | "requires": { 61 | "$id": "#/properties/actions/properties/requires", 62 | "title": "Required prerequsites", 63 | "description": "The CASE prerequisites that apply to this action", 64 | "anyOf": [ 65 | { 66 | "type": "string" 67 | }, 68 | { 69 | "type": "array" 70 | }, 71 | { 72 | "type": "object" 73 | } 74 | ], 75 | "additionalProperties": true 76 | }, 77 | "k8sPermissions": { 78 | "$id": "#/properties/actions/properties/k8sPermissions", 79 | "type": "object", 80 | "title": "Kubernetes permission rules", 81 | "description": "The Kubernetes permissions that apply to this action", 82 | "required": [ 83 | "rules" 84 | ], 85 | "properties": { 86 | "rules": { 87 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules", 88 | "type": "array", 89 | "title": "Kubernetes API permissions", 90 | "description": "The Kubernetes API permissions to be used with the SubjectAccessReview API, also known as the can-i authorization commmand", 91 | "items": { 92 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items", 93 | "type": "object", 94 | "title": "Kubernetes permissions items schema", 95 | "description": "The Kubernetes API permissions", 96 | "required": [ 97 | "rule" 98 | ], 99 | "properties": { 100 | "ifExpression": { 101 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/ifExpression", 102 | "anyOf": [ 103 | { 104 | "type": "string" 105 | }, 106 | { 107 | "type": "array" 108 | }, 109 | { 110 | "type": "object" 111 | } 112 | ], 113 | "additionalProperties": true 114 | }, 115 | "rule": { 116 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/rule", 117 | "type": "object", 118 | "title": "Kubernetes permissions item rule", 119 | "description": "The Kubernetes API Permissions to be used with the SubjectAccessReview API, also known as the can-i authorization commmand", 120 | "required": [ 121 | "group", 122 | "resource", 123 | "verbs" 124 | ], 125 | "properties": { 126 | "group": { 127 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/rule/properties/group", 128 | "type": "string", 129 | "title": "Kubernetes APIGroup", 130 | "description": "The Kubernetes APIGroup for the resource", 131 | "default": "", 132 | "examples": [ 133 | "extensions", 134 | "", 135 | "policy" 136 | ], 137 | "pattern": "^(.*)$" 138 | }, 139 | "resource": { 140 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/rule/properties/resource", 141 | "type": "string", 142 | "title": "Kubernetes resource", 143 | "description": "One of the existing resource types. \"*\" means all. (required)", 144 | "default": "", 145 | "examples": [ 146 | "EtcdBackup" 147 | ], 148 | "pattern": "^(.*)$" 149 | }, 150 | "subresource": { 151 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/rule/properties/subresource", 152 | "type": "string", 153 | "title": "Kubernetes subresource", 154 | "description": "One of the existing subresource types. \"\" means none. (optional)", 155 | "default": "", 156 | "examples": [ 157 | "status" 158 | ], 159 | "pattern": "^(.*)$" 160 | }, 161 | "verbs": { 162 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/rule/properties/verbs", 163 | "type": "array", 164 | "items": { 165 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/rule/properties/verbs/items", 166 | "type": "string", 167 | "title": "Kubernetes verb", 168 | "description": "A kubernetes resource API verb, like: get, list, watch, create, update, delete, proxy. \"*\" means all. (required)", 169 | "default": "", 170 | "examples": [ 171 | "*", 172 | "get", 173 | "watch" 174 | ], 175 | "pattern": "^(.*)$" 176 | } 177 | }, 178 | "name": { 179 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/rule/properties/name", 180 | "type": "string", 181 | "title": "Resource name", 182 | "description": "The name of the resource being requested. \"\" (empty) means all. (optional)", 183 | "default": "", 184 | "examples": [ 185 | "myResource" 186 | ], 187 | "pattern": "^(.*)$" 188 | }, 189 | "namespace": { 190 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/rule/properties/namespace", 191 | "type": "string", 192 | "title": "Resource namespace", 193 | "description": "The namespace of the action being requested. (Optional, default=all)", 194 | "default": "", 195 | "examples": [ 196 | "myResource" 197 | ], 198 | "pattern": "^(.*)$" 199 | }, 200 | "version": { 201 | "$id": "#/properties/actions/properties/k8sPermissions/properties/rules/items/rule/properties/version", 202 | "type": "string", 203 | "title": "Resource version", 204 | "description": "The version of the resource. (Optional, default='*')", 205 | "default": "'*'", 206 | "examples": [ 207 | "*", 208 | "v1", 209 | "v1beta1" 210 | ], 211 | "pattern": "^(.*)$" 212 | } 213 | } 214 | } 215 | } 216 | } 217 | } 218 | } 219 | } 220 | } 221 | } 222 | } 223 | } 224 | } 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /schema/certification.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 5 | "type": "object", 6 | "title": "The Root Schema", 7 | "description": "The root of the certification schema", 8 | "required": [ 9 | "certification" 10 | ], 11 | "properties": { 12 | "certification": { 13 | "$id": "#/properties/certification", 14 | "title": "Certification", 15 | "description": "The certification schema", 16 | "type": "object", 17 | "required": [ 18 | "id", 19 | "type", 20 | "issueDate", 21 | "expirationDate", 22 | "terms", 23 | "provider" 24 | ], 25 | "properties": { 26 | "metadata": { 27 | "$ref": "metadata.json#/definitions/metadataRef" 28 | }, 29 | "id": { 30 | "$id": "#/definitions/ibmCertRef/properties/id", 31 | "type": "string", 32 | "title": "Certification identifier", 33 | "description": "The identifier of the certification", 34 | "default": "", 35 | "examples": [ 36 | "75b05dfb-8988-4caa-8a6c-36f8ae5fe211" 37 | ], 38 | "pattern": "^(.*)$" 39 | }, 40 | "provider": { 41 | "$id": "#/definitions/ibmCertRef/properties/provider", 42 | "type": "string", 43 | "title": "Certification provider", 44 | "description": "The certification provider identifier. A provider must be unique by vendor or certification authority", 45 | "default": "", 46 | "examples": [ 47 | "ibm" 48 | ] 49 | }, 50 | "type": { 51 | "$id": "#/definitions/ibmCertRef/properties/type", 52 | "type": "string", 53 | "title": "Certification type", 54 | "description": "The type of certification.", 55 | "default": "", 56 | "examples": [ 57 | "ccp", 58 | "cc", 59 | "mc" 60 | ] 61 | }, 62 | "issueDate": { 63 | "type": "string", 64 | "title": "Certification issue date", 65 | "description": "The date in which the certification was issued in the format MM/DD/YYYY", 66 | "default": "", 67 | "examples": [ 68 | "03/01/2019", 69 | "12/01/2019" 70 | ], 71 | "pattern": "^([1-9]|0[1-9]|1[012])/([1-9]|0[1-9]|[12][0-9]|3[01])/20[0-9]{2}$" 72 | }, 73 | "expirationDate": { 74 | "$id": "#/definitions/ibmCertRef/properties/expirationDate", 75 | "title": "Certification expiration date", 76 | "description": "The date in which the certification expires in the format MM/DD/YYYY", 77 | "default": "", 78 | "examples": [ 79 | "02/28/2020", 80 | "12/31/202" 81 | ], 82 | "pattern": "^([1-9]|0[1-9]|1[012])/([1-9]|0[1-9]|[12][0-9]|3[01])/20[0-9]{2}$" 83 | }, 84 | "terms": { 85 | "$id": "#/definitions/ibmCertRef/properties/terms", 86 | "type": "string", 87 | "title": "Certification terms", 88 | "description": "The terms of this certification.", 89 | "default": "", 90 | "examples": [ 91 | "Valid from date of issue. Security vulnerability management and enhancements are delivered on the latest version of the chart and images" 92 | ], 93 | "pattern": "^(.*)$" 94 | }, 95 | "exceptions": { 96 | "$id": "#/definitions/ibmCertRef/properties/exceptions", 97 | "type": "array", 98 | "title": "Certification exceptions", 99 | "description": "An array of exception(s) granted during certification", 100 | "items": { 101 | "type": "object", 102 | "required": [ 103 | "id", 104 | "description", 105 | "remediation" 106 | ], 107 | "properties": { 108 | "id": { 109 | "$id": "#/definitions/ibmCertRef/exceptions/properties/id", 110 | "title": "Exception identifier", 111 | "description": "Unique string identifier for exception assigned during certification", 112 | "type": "string", 113 | "default": "", 114 | "examples": [ 115 | "12345" 116 | ], 117 | "pattern": "^(.*)$" 118 | }, 119 | "description": { 120 | "$id": "#/definitions/ibmCertRef/exceptions/properties/description", 121 | "title": "Exception description", 122 | "description": "The description of the exception for documentation", 123 | "type": "string", 124 | "default": "", 125 | "pattern": "^(.*)$" 126 | }, 127 | "remediation": { 128 | "$id": "#/definitions/ibmCertRef/exceptions/properties/remediation", 129 | "title": "Exception remediation plan", 130 | "description": "The planned remediation of the exception for documentation", 131 | "type": "string", 132 | "default": "", 133 | "pattern": "^(.*)$" 134 | } 135 | } 136 | } 137 | } 138 | } 139 | }, 140 | "resources": { 141 | "$id": "#/properties/resources", 142 | "type": "object", 143 | "title": "Resources", 144 | "description": "The resources schema", 145 | "required": [ 146 | "resourceDefs" 147 | ], 148 | "properties": { 149 | "metadata": { 150 | "$ref": "metadata.json#/definitions/metadataRef" 151 | }, 152 | "resourceDefs": { 153 | "$id": "#/properties/resources/resourceDefs", 154 | "type": "object", 155 | "title": "Resource definitions", 156 | "description": "The resource definitions", 157 | "properties": { 158 | "files": { 159 | "$id": "#/properties/resources/properties/files", 160 | "title": "Files", 161 | "description": "Other embedded files", 162 | "type": "array", 163 | "required": [ 164 | "ref" 165 | ], 166 | "items": { 167 | "type": "object", 168 | "properties": { 169 | "metadata": { 170 | "$ref": "metadata.json#/definitions/metadataRef" 171 | }, 172 | "mediaType": { 173 | "$id": "#/properties/resources/properties/files/mediaType", 174 | "type":"string", 175 | "title": "Media type", 176 | "description": "Media Type (MIME) of the resource.", 177 | "default": "text/plain" 178 | }, 179 | "ref": { 180 | "$id": "#/properties/resources/properties/files/ref", 181 | "title": "File name reference", 182 | "description": "The file name reference in the files directory.", 183 | "type": "string" 184 | } 185 | }, 186 | "required": ["ref"] 187 | } 188 | } 189 | } 190 | } 191 | } 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /schema/digests.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": { 3 | "digestRef": { 4 | "$id": "#/definitions/digestRef", 5 | "type": "object", 6 | "required": [ 7 | "digest" 8 | ], 9 | "properties": { 10 | "digest": { 11 | "title": "Digest", 12 | "description": "The digest", 13 | "type": "string", 14 | "pattern": "^(.*)$" 15 | }, 16 | "size": { 17 | "title": "Size", 18 | "description": "Size in bytes", 19 | "type": "integer" 20 | }, 21 | "skip": { 22 | "title": "Skip", 23 | "description": "If true, skip this entry when evaluating the digest", 24 | "type": "boolean" 25 | } 26 | } 27 | }, 28 | "digestsRef": { 29 | "$id": "#/definitions/digestsRef", 30 | "type": "array", 31 | "title": "Digests", 32 | "description": "Digest references", 33 | "items": { 34 | "$ref": "#/definitions/digestRef" 35 | } 36 | } 37 | }, 38 | "$schema": "http://json-schema.org/draft-07/schema#", 39 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 40 | "type": "object", 41 | "title": "Root Schema", 42 | "description": "The root of the digests schema", 43 | "required": [ 44 | "digests" 45 | ], 46 | "properties": { 47 | "digests": { 48 | "$id": "#/properties/digests", 49 | "type": "object", 50 | "title": "Digests", 51 | "description": "Contains the digest definitions for the resources defined by the CASE", 52 | "required": [ 53 | "digestDefs" 54 | ], 55 | "properties": { 56 | "metadata": { 57 | "$ref": "metadata.json#/definitions/metadataRef" 58 | }, 59 | "digestDefs": { 60 | "$id": "#/properties/digests/digestDefs", 61 | "type": "object", 62 | "title": "Digest definitions", 63 | "description": "Contains the digest for the resources defined by the CASE", 64 | "properties": { 65 | "readme": { 66 | "title": "README digest", 67 | "description": "The digest of the CASE README.md", 68 | "$ref": "#/definitions/digestRef" 69 | }, 70 | "inventory": { 71 | "type": "object", 72 | "$id": "#/properties/inventory", 73 | "title": "Inventory items digests", 74 | "description": "The digests for the CASE inventory items", 75 | "patternProperties": { 76 | ".*": { 77 | "$id": "#/properties/inventory/wildcard", 78 | "type": "object", 79 | "title": "Inventory item digest", 80 | "description": "The digests for the specified inventory item", 81 | "properties": { 82 | "readme": { 83 | "title": "README digest", 84 | "description": "The digest of the inventory item README.md", 85 | "$ref": "#/definitions/digestRef" 86 | }, 87 | "resources": { 88 | "$id": "#/properties/inventory/wildcard/resources", 89 | "title": "Resources digests", 90 | "description": "The inventory item resource digests", 91 | "type": "object", 92 | "properties": { 93 | "resourceDefs": { 94 | "$id": "#/properties/inventory/wildcard/resources/resourceDefs", 95 | "title": "Resource digests", 96 | "description": "The inventory item resource definition digests", 97 | "type": "object", 98 | "properties": { 99 | "cases": { 100 | "title": "CASE digests", 101 | "description": "The digests for any CASEs in the inventory item", 102 | "$ref": "#/definitions/digestsRef" 103 | }, 104 | "helmCharts": { 105 | "title": "Helm chart digests", 106 | "description": "The digests for any Helm charts in the inventory item", 107 | "$ref": "#/definitions/digestsRef" 108 | }, 109 | "files": { 110 | "title": "File digests", 111 | "description": "The digests for any files in the inventory item", 112 | "$ref": "#/definitions/digestsRef" 113 | }, 114 | "containerImages": { 115 | "title": "Container image digests", 116 | "description": "The digests for any container images in the inventory item", 117 | "$ref": "#/definitions/digestsRef" 118 | } 119 | } 120 | } 121 | } 122 | } 123 | } 124 | } 125 | } 126 | }, 127 | "licenses": { 128 | "type": "object", 129 | "$id": "#/properties/licenses", 130 | "title": "Product license files digest", 131 | "description": "The digest for the product license files", 132 | "patternProperties": { 133 | ".*": { 134 | "$ref": "#/definitions/digestRef" 135 | } 136 | } 137 | }, 138 | "license": { 139 | "$id": "#/properties/licenses", 140 | "title": "CASE license digest", 141 | "description": "The digest for the CASE license", 142 | "$ref": "#/definitions/digestRef" 143 | }, 144 | "case": { 145 | "$id": "#/properties/case", 146 | "title": "CASE digest", 147 | "description": "The canonical CASE digest", 148 | "$ref": "#/definitions/digestRef" 149 | } 150 | } 151 | } 152 | } 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /schema/inventory.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 4 | "type": "object", 5 | "title": "Root Schema", 6 | "description": "The root of the inventory schema", 7 | "definitions": {}, 8 | "required": [ 9 | "inventory" 10 | ], 11 | "properties": { 12 | "inventory": { 13 | "type": "object", 14 | "$id": "#/properties/inventory", 15 | "title": "Inventory data", 16 | "description": "Information related to the inventory item", 17 | "properties": { 18 | "metadata": { 19 | "$ref": "metadata.json#/definitions/metadataRef" 20 | }, 21 | "k8sScope": { 22 | "$id": "#/properties/inventory/k8sScope", 23 | "type": "string", 24 | "title": "Kubernetes scope", 25 | "description": "The Kubernetes scope this inventory item applies to.", 26 | "default": "", 27 | "examples": [ 28 | "namespace", 29 | "cluster" 30 | ], 31 | "pattern": "^(.*)$" 32 | }, 33 | "groups": { 34 | "$id": "#/properties/resources/properties/resourceDefs/properties/containerImages/groups", 35 | "title": "Groups", 36 | "description": "The groups an image belongs to", 37 | "type": "object", 38 | "patternProperties": { 39 | "^[a-z_$][A-Za-z0-9_$]{0,49}$": { 40 | "type": "object" 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /schema/logical-grammar.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 4 | "definitions": { 5 | "logicalOps": { 6 | "$id" : "#/definitions/logicalOps", 7 | "title": "Logical grammar", 8 | "description": "A logical expression of either unary or binary origin", 9 | "type": "object", 10 | "propertyNames": { 11 | "pattern": "^(and|or|!)$" 12 | }, 13 | "patternProperties": { 14 | "^(and|or)$": { 15 | "type": "array", 16 | "items": { 17 | "anyOf": [ 18 | { 19 | "$ref": "#/definitions/logicalOps" 20 | }, 21 | { 22 | "$ref": "#/definitions/resolution" 23 | } 24 | ] 25 | } 26 | }, 27 | "^(!)$": { 28 | "type": "array", 29 | "maxItems": 1, 30 | "items": { 31 | "anyOf": [ 32 | { 33 | "$ref": "#/definitions/logicalOps" 34 | }, 35 | { 36 | "$ref": "#/definitions/resolution" 37 | } 38 | ] 39 | } 40 | } 41 | } 42 | }, 43 | "resolution": { 44 | "title": "JSON pointer", 45 | "description": "A JSON pointer defines a string syntax for identifying a specific value with a JSON document", 46 | "$id": "#/definitions/resolution", 47 | "default": "", 48 | "examples": [ 49 | "/case/prereqs/k8sDistros/openshift", 50 | "/case/prereqs/k8sResources/etcdControllerPSP" 51 | ], 52 | "anyOf": [ 53 | { 54 | "type": "string", 55 | "pattern": "^(\/[a-z$_][a-zA-Z0-9_$]*)*$" 56 | }, 57 | { 58 | "type": "boolean" 59 | } 60 | ] 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /schema/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 4 | "definitions": { 5 | "metadataRef": { 6 | "$id": "#/definitions/metadataRef", 7 | "title": "Metadata reference", 8 | "description": "Various properties applicable to an object", 9 | "type":"object", 10 | "properties": { 11 | "specVersion": { 12 | "title": "Specification version", 13 | "description": "The version of the specification this object implements.", 14 | "type": "string", 15 | "default": "1.0.0", 16 | "examples": [ 17 | "1.0.0" 18 | ], 19 | "pattern": "^(.*)$" 20 | }, 21 | "name": { 22 | "title": "Name", 23 | "description": "The name of the object for use in api addressibility", 24 | "type": "string", 25 | "default": "", 26 | "examples": [ 27 | "myResourceName" 28 | ], 29 | "pattern": "^[a-z_$][A-Za-z0-9_$]{0,49}$" 30 | }, 31 | "description": { 32 | "title": "Description", 33 | "description": "The description of the object for use as internal documentation", 34 | "type": "string", 35 | "default": "", 36 | "examples": [ 37 | "This is my resource" 38 | ], 39 | "pattern": "^(.*)$" 40 | }, 41 | "displayName": { 42 | "title": "Display name", 43 | "description": "The name of this object to be displayed to a user interface", 44 | "type": "string", 45 | "default": "", 46 | "examples": [ 47 | "My Resource" 48 | ], 49 | "pattern": "^(.*){1,20}$" 50 | }, 51 | "displayDescription": { 52 | "title": "Display description", 53 | "description": "The description of this object to be displayed to a user interface", 54 | "type": "string", 55 | "default": "", 56 | "examples": [ 57 | "This is my resource which has some interesting information." 58 | ], 59 | "pattern": "^(.*)$" 60 | } 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /schema/repo-index.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 5 | "type": "object", 6 | "title": "The 'Repository Index Schema' for a CASE repository", 7 | "required": [ 8 | "apiVersion", 9 | "entries" 10 | ], 11 | "properties": { 12 | "apiVersion" : { 13 | "$id": "#/properties/apiVersion", 14 | "type": "string", 15 | "title": "The api version of the 'Repository Index Schema'.", 16 | "default": "", 17 | "examples": [ 18 | "1.0.0" 19 | ], 20 | "pattern": "^(.*)$" 21 | }, 22 | "entries": { 23 | "$id": "#/properties/entries", 24 | "type": "object", 25 | "title": "The Entries definitions", 26 | "additionalProperties": false, 27 | "patternProperties": { 28 | "^[a-z_$-][A-Za-z0-9_$-]{0,49}$": { 29 | "title": "A CASE name", 30 | "required": [ 31 | "latestAppVersion", 32 | "latestVersion" 33 | ], 34 | "properties": { 35 | "latestAppVersion": { 36 | "$id": "#/properties/entries/latestAppVersion", 37 | "type": "string", 38 | "title": "The app version associated with the latest version of the CASE.", 39 | "default": "", 40 | "examples": [ 41 | "1.0.0" 42 | ], 43 | "pattern": "^(.*)$" 44 | }, 45 | "latestVersion": { 46 | "$id": "#/properties/entries/latestVersion", 47 | "type": "string", 48 | "title": "The latest version of the specified CASE.", 49 | "default": "", 50 | "examples": [ 51 | "1.0.0" 52 | ], 53 | "pattern": "^(.*)$" 54 | }, 55 | "latestAppSemver": { 56 | "$id": "#/properties/entries/latestAppSemver", 57 | "type": "string", 58 | "title": "The latest semver application version of the specified CASE.", 59 | "default": "", 60 | "examples": [ 61 | "1.0.0" 62 | ], 63 | "pattern": "^(.*)$" 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /schema/repo-product-index.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 5 | "type": "object", 6 | "title": "The 'Product Index Schema' for a CASE repository", 7 | "required": [ 8 | "apiVersion", 9 | "latestVersion", 10 | "latestAppVersion", 11 | "versions" 12 | ], 13 | "properties": { 14 | "apiVersion" : { 15 | "$id": "#/properties/apiVersion", 16 | "type": "string", 17 | "title": "The api version of the 'Product Index Schema'.'", 18 | "default": "", 19 | "examples": [ 20 | "1.0.0" 21 | ], 22 | "pattern": "^(.*)$" 23 | }, 24 | "latestVersion": { 25 | "$id": "#/properties/latestVersion", 26 | "type": "string", 27 | "title": "The latest version of this CASE", 28 | "default": "", 29 | "examples": [ 30 | "1.0.0" 31 | ], 32 | "pattern": "^(.*)$" 33 | }, 34 | "latestAppVersion": { 35 | "$id": "#/properties/latestAppVersion", 36 | "type": "string", 37 | "title": "The version of the application represented by this case", 38 | "default": "0.0.1", 39 | "examples": [ 40 | "1.0.0" 41 | ], 42 | "pattern": "^(.*)$" 43 | }, 44 | "latestAppSemver": { 45 | "$id": "#/properties/latestAppSemver", 46 | "type": "string", 47 | "title": "The semver of the application represented by this case", 48 | "default": "0.0.1", 49 | "examples": [ 50 | "1.0.0" 51 | ], 52 | "pattern": "^(.*)$" 53 | }, 54 | "versions": { 55 | "$id": "#/properties/versions", 56 | "type": "object", 57 | "title": "The List of versions of this CASE", 58 | "additionalProperties": false, 59 | "patternProperties": { 60 | "^(0|[1-9]*).(0|[1-9]*).(0|[1-9]*)": { 61 | "type": "object", 62 | "title": "A specific CASE version.", 63 | "required": [ 64 | "appVersion" 65 | ], 66 | "properties": { 67 | "appVersion": { 68 | "$id": "#/properties/versions/properties/appVersion", 69 | "type": "string", 70 | "title": "The appplication version associated with this CASE version", 71 | "default": "", 72 | "examples": [ 73 | "1.0.0", 74 | "1.0.1" 75 | ], 76 | "pattern": "^(.*)$" 77 | }, 78 | "appSemver": { 79 | "$id": "#/properties/versions/properties/appSemver", 80 | "type": "string", 81 | "title": "The appplication semantic version associated with this CASE version", 82 | "default": "", 83 | "examples": [ 84 | "1.0.0", 85 | "1.0.1" 86 | ], 87 | "pattern": "^(.*)$" 88 | } 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /schema/repo-product-version.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 5 | "type": "object", 6 | "title": "The 'Product Version Index Schema' for a CASE repository", 7 | "description": "The 'Product Version Index Schema' for a CASE repository. This is essentially similar to case.yaml, with additional values.", 8 | "required": [ 9 | "apiVersion", 10 | "case" 11 | ], 12 | "properties": { 13 | "apiVersion" : { 14 | "$id": "#/properties/apiVersion", 15 | "type": "string", 16 | "title": "The api version of the 'Product Version Index Schema'.", 17 | "default": "", 18 | "examples": [ 19 | "1.0.0" 20 | ], 21 | "pattern": "^(.*)$" 22 | }, 23 | "created": { 24 | "$id": "#/properties/created", 25 | "type": "string", 26 | "title": "The created date and time for this CASE", 27 | "default": "", 28 | "examples": [ 29 | "2019-09-30T16:00:00.45234224-06:00" 30 | ], 31 | "pattern": "^(.*)$" 32 | }, 33 | "digest": { 34 | "$id": "#/properties/digest", 35 | "type": "string", 36 | "title": "The CASE digest", 37 | "default": "", 38 | "examples": [ 39 | "etcd-operator" 40 | ], 41 | "pattern": "^(.*)$" 42 | }, 43 | "case": { 44 | "title": "The CASE descriptor.", 45 | "$ref": "case.json#/definitions/caseRef" 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /schema/resource-groups.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 5 | "type": "object", 6 | "title": "Root schema", 7 | "description": "The root of the resourceGroups schema", 8 | "required": [ 9 | "resourceGroups" 10 | ], 11 | "properties": { 12 | "resourceGroups": { 13 | "$id": "#/properties/resourceGroups", 14 | "type": "object", 15 | "title": "ResourceGroups", 16 | "description": "Contains the resource group definitions for the CASE", 17 | "required": [ 18 | "resourceGroupsDefs" 19 | ], 20 | "properties": { 21 | "resourceGroupsDefs": { 22 | "$id": "#/properties/resourceGroups/resourceGroupsDefs", 23 | "type": "object", 24 | "title": "Resource groups definitions", 25 | "description": "Defines the resourceGroups for the CASE", 26 | "additionalProperties": false, 27 | "patternProperties": { 28 | "^[a-z_$][A-Za-z0-9_$]{0,49}$": { 29 | "type": "object", 30 | "title": "Resource group", 31 | "description": "Defines a resource group for a CASE", 32 | "required": [ 33 | "groups" 34 | ], 35 | "properties": { 36 | "metadata ": { 37 | "$ref": "metadata.json#/definitions/metadataRef" 38 | }, 39 | "groups": { 40 | "$id": "#/properties/resourceGroups/resourceGroupsDefs/properties/groups", 41 | "title": "Groups", 42 | "description": "List of groups in the specified resource group", 43 | "type": "array", 44 | "required": [ 45 | "name" 46 | ], 47 | "items": { 48 | "type": "object", 49 | "properties": { 50 | "name": { 51 | "$id": "#/properties/resources/properties/groups/name", 52 | "type":"string", 53 | "title": "Group name", 54 | "description": "A group name", 55 | "default": "text/plain" 56 | } 57 | }, 58 | "required": ["name"] 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /schema/roles.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": {}, 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 5 | "type": "object", 6 | "title": "The Root Schema", 7 | "required": [ 8 | "roles" 9 | ], 10 | "properties": { 11 | "roles": { 12 | "$id": "#/properties/roles", 13 | "type": "object", 14 | "title": "Resources", 15 | "description": "The resources schema", 16 | "required": [ 17 | "roleDefs" 18 | ], 19 | "properties": { 20 | "metadata": { 21 | "$ref": "metadata.json#/definitions/metadataRef" 22 | }, 23 | "roleDefs": { 24 | "$id": "#/properties/roles/roleDefs", 25 | "type": "object", 26 | "title": "Role definitions", 27 | "description": "The role definitions", 28 | "additionalProperties": false, 29 | "patternProperties": { 30 | "^[a-z_$][A-Za-z0-9_$]{0,49}$" : { 31 | "$id": "#/properties/roles/patternProperties", 32 | "type": "object", 33 | "title": "Roles", 34 | "description": "Roles", 35 | "required": [ 36 | "metadata" 37 | ], 38 | "properties": { 39 | "metadata": { 40 | "$ref": "metadata.json#/definitions/metadataRef" 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /schema/signature.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": { 3 | "signatureRef": { 4 | "$id": "#/definitions/signatureRef", 5 | "type": "object", 6 | "required": [ 7 | "certificate", 8 | "chain" 9 | ], 10 | "properties": { 11 | "certificate": { 12 | "title": "Certificate", 13 | "description": "The base64 encoded certificate", 14 | "type": "string" 15 | }, 16 | "chain": { 17 | "title": "Chain", 18 | "description": "The certificaate chain", 19 | "type": "string" 20 | } 21 | } 22 | } 23 | }, 24 | "$schema": "http://json-schema.org/draft-07/schema#", 25 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 26 | "type": "object", 27 | "title": "The Root Schema", 28 | "description": "The root of the signature schema", 29 | "required": [ 30 | "headers", 31 | "data", 32 | "x509Certificates", 33 | "signature" 34 | ], 35 | "properties": { 36 | "headers": { 37 | "$id": "#/properties/headers", 38 | "type": "object", 39 | "title": "Headers", 40 | "description": "The signature header", 41 | "required": [ 42 | "alg", 43 | "version" 44 | ], 45 | "properties": { 46 | "alg": { 47 | "$id": "#/properties/headers/alg", 48 | "type": "string", 49 | "title": "Algorithm", 50 | "description": "The algorithm used to encrypt the signature." 51 | }, 52 | "version": { 53 | "$id": "#/properties/headers/version", 54 | "type": "string", 55 | "title": "Version", 56 | "description": "The version of the CASE spec being used." 57 | } 58 | } 59 | }, 60 | "data": { 61 | "$id": "#/properties/data", 62 | "type": "object", 63 | "title": "Data", 64 | "description": "The digest data for the signature.", 65 | "required": [ 66 | "digest" 67 | ], 68 | "properties": { 69 | "digest": { 70 | "$id": "#/properties/data/digest", 71 | "type": "string", 72 | "title": "Digest", 73 | "description": "The SHA-256 hash of the canonical JSON version of the CASE." 74 | } 75 | } 76 | }, 77 | "x509Certificates": { 78 | "$id": "#/properties/x509Certificates", 79 | "type": "array", 80 | "title": "x509 Certificates", 81 | "description": "Array of base64-encoded certificates used for decrypting the signature.", 82 | "items": { 83 | "$ref": "#/definitions/signatureRef" 84 | } 85 | }, 86 | "signature": { 87 | "$id": "#/properties/signature", 88 | "type": "string", 89 | "title": "Signature", 90 | "description": "The digital signature for the CASE." 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /schema/version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://raw.githubusercontent.com/ibm/case/master/schema/root.json", 4 | "definitions": { 5 | "semverRef": { 6 | "$id": "#/definitions/semverRef", 7 | "title": "Semantic Version", 8 | "description": "Defines what a semver looks like in the CASE JSON scheme", 9 | "type": "string", 10 | "default": "", 11 | "examples": [ 12 | "1.0.0", 13 | "1.0.0+20191108.173000", 14 | "1.0.0+20191108.173000.patch1", 15 | "1.0.0-beta.1", 16 | "1.0.0-beta.1+20191108.173000.patch1" 17 | ], 18 | "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(\\d{8}\\.[0-2]\\d[0-5]\\d[0-5]\\d)(?:\\.(?:[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /utilities/createArchive.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Create a CASE archive from a CASE directory such that the SHA digest of the archive is consistent. 4 | 5 | # Usage: 6 | # createArchive.sh 7 | 8 | if [ "$#" -lt 1 ]; then 9 | echo "Usage: createArchive.sh " 10 | exit 1 11 | fi 12 | 13 | if ! type yq >/dev/null 2>&1; then 14 | echo 'Error: yq is not installed.' 15 | exit 1 16 | fi 17 | 18 | CASEDIR=$1 19 | 20 | CASENAME=$(yq r $CASEDIR/case.yaml name) 21 | CASEVERSION=$(yq r $CASEDIR/case.yaml version) 22 | 23 | CURDIR=$(pwd) 24 | cd $CASEDIR/.. 25 | 26 | # tar + gz the file. Use the -n option to avoid adding a timestamp. 27 | ARCHIVENAME="$CASENAME-$CASEVERSION.tgz" 28 | tar -cf - -C "$CASEDIR/.." "$CASENAME/" | gzip -nc > "$CURDIR/$ARCHIVENAME" 29 | 30 | #Display teh SHA 31 | if type shasum >/dev/null 2>&1; then 32 | shasum -a 256 "$CURDIR/$ARCHIVENAME" | cut -f1 -d' ' 33 | fi 34 | 35 | cd $CURDIR 36 | -------------------------------------------------------------------------------- /utilities/processFiles.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROGNAME=$(basename "$0") 4 | USAGE="Usage: $PROGNAME (-s | --source_dir) (-d | --destination_dir) (-h | --help) 5 | 6 | This script will recursively iterate over files and folders and create a resources.yaml 7 | with the resources.resourceDefs.files filled in with an entry for each file. 8 | 9 | OPTIONS: 10 | -s,--source_dir Source files directory (error if not a files directory) 11 | -d,--destination_dir Target directory for output 12 | -h,--help Display this message 13 | " 14 | 15 | while [[ $# -gt 0 ]]; do 16 | case "$1" in 17 | -s|--source_dir) 18 | SOURCE="$2" 19 | shift # past argument 20 | shift # past value 21 | ;; 22 | -d|--destination_dir) 23 | DESTINATION="$2" 24 | shift # past argument 25 | shift # past value 26 | ;; 27 | -h|--help) 28 | echo "$USAGE" 29 | exit 0 30 | ;; 31 | *) # unknown option 32 | POSITIONAL+=("$1") # save it in an array for later 33 | shift # past argument 34 | ;; 35 | esac 36 | done 37 | 38 | if [[ -z "${SOURCE}" || -z "${DESTINATION}" ]]; then 39 | echo "Incorrect arguments." 40 | echo "${USAGE}" 41 | exit 1 42 | fi 43 | 44 | if [[ ! -d "${SOURCE}" ]]; then 45 | echo "source_dir argument is not a directory" 46 | exit 1 47 | fi 48 | 49 | if [[ ! -d "${DESTINATION}" ]]; then 50 | echo "destination_dir argument is not a directory" 51 | exit 1 52 | fi 53 | 54 | if ! SOURCE_FULL_PATH=$(cd "${SOURCE}" >/dev/null || exit; echo "${PWD}"); then 55 | echo "An error occurred accessing source_dir argument ${SOURCE}" 56 | exit 1 57 | fi 58 | 59 | if [[ $(basename -- "${SOURCE_FULL_PATH}") != "files" ]]; then 60 | echo "source_dir argument should be a CASE files directory" 61 | exit 1 62 | fi 63 | 64 | # Writes out header for ${DESTINATION} file 65 | function write_header() { 66 | cat << EOF > "${DESTINATION}"/resources.yaml 67 | resources: 68 | metadata: 69 | name: "CHANGE ME" 70 | resourceDefs: 71 | files: 72 | EOF 73 | } 74 | 75 | # Scans through the provided file list and write output to ${DESTINATION} file, overwriting any previous data 76 | # Args: FILES - a return separated list of files 77 | # Returns 0 if success 78 | # Returns 1 if failure 79 | function scan_files_and_write_output() { 80 | # A return separated list of files 81 | local FILES=$1 82 | # the default filetype 83 | local INITIAL_FILETYPE 84 | # the potentially overridden filetype 85 | local FINAL_FILETYPE 86 | # overwrite file with preliminary data and bail out if this fails 87 | if ! write_header; then 88 | echo "Unable to write header" 89 | return 1 90 | fi 91 | # iterate over each line 92 | while read -r line; do 93 | echo "... $line ..." 94 | # get the mimetype for the file and adjust it for any known filetypes 95 | if INITIAL_FILETYPE=$(file -b -L --mime-type "${line}"); then 96 | if [[ ${INITIAL_FILETYPE} == "text/plain" && $(basename -- "${line}") == manifest.yaml ]]; then 97 | FINAL_FILETYPE="application/vnd.case.resource.image.manifest.v1" 98 | elif [[ ( ${INITIAL_FILETYPE} == "text/plain" || ${INITIAL_FILETYPE} == "inode/x-empty" ) && $(basename -- "${line}") == *.yaml ]]; then 99 | FINAL_FILETYPE="application/vnd.case.resource.k8s.v1+yaml" 100 | elif [[ ${INITIAL_FILETYPE} == text/* && $(basename -- "${line}") == launch.sh ]]; then 101 | FINAL_FILETYPE="application/vnd.case.resource.script.bash.v1+launcher" 102 | elif [[ ${INITIAL_FILETYPE} == text/* && $(basename -- "${line}") == *.sh ]]; then 103 | FINAL_FILETYPE="application/vnd.case.resource.script.bash.v1" 104 | else 105 | FINAL_FILETYPE="${INITIAL_FILETYPE}" 106 | fi 107 | fi 108 | cat << EOF >> "${DESTINATION}"/resources.yaml 109 | - mediaType: ${FINAL_FILETYPE} 110 | ref: ${line#$SOURCE_FULL_PATH/} 111 | EOF 112 | done <<< "${FILES}" 113 | } 114 | 115 | # starting point for this script 116 | function main() { 117 | # use find to dereference any symbolic links and report any files it finds 118 | if ! FILES=$(find -L "${SOURCE_FULL_PATH}" -name "*" -type f 2>/dev/null | grep '.' | sort); then 119 | echo "No files found. Exting without generating a file." 120 | return 1 121 | fi 122 | 123 | # does destination file exist? 124 | if [ -w "${DESTINATION}"/resources.yaml ]; then 125 | echo "File exists. Overwrite? y/n" 126 | read -r ANSWER 127 | case $ANSWER in 128 | [yY] ) scan_files_and_write_output "${FILES}" ;; 129 | [nN] ) echo "Exiting without making changes" ;; 130 | esac 131 | else 132 | # destination file doesn't exist or no write permission granted 133 | scan_files_and_write_output "${FILES}" 134 | fi 135 | } 136 | 137 | main 138 | --------------------------------------------------------------------------------