diff --git a/api/hlf.kungfusoftware.es/v1alpha1/hlf_types.go b/api/hlf.kungfusoftware.es/v1alpha1/hlf_types.go index f1cb5877..e685ce74 100644 --- a/api/hlf.kungfusoftware.es/v1alpha1/hlf_types.go +++ b/api/hlf.kungfusoftware.es/v1alpha1/hlf_types.go @@ -134,6 +134,11 @@ type GRPCProxy struct { // +nullable ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets"` } +type AddressOverride struct { + From string `json:"from"` + To string `json:"to"` + CACertsFile string `json:"caCertsFile"` +} // FabricPeerSpec defines the desired state of FabricPeer type FabricPeerSpec struct { @@ -148,6 +153,23 @@ type FabricPeerSpec struct { // +kubebuilder:default:={} PodLabels map[string]string `json:"podLabels"` + // +nullable + // +optional + // +kubebuilder:validation:Optional + // +kubebuilder:default:={} + DeliveryClientaddressOverrides []AddressOverride `json:"deliveryClientaddressOverrides"` + // +optional + // +nullable + // +kubebuilder:validation:Optional + // +kubebuilder:default:={} + Volumes []corev1.Volume `json:"volumes"` + + // +optional + // +nullable + // +kubebuilder:validation:Optional + // +kubebuilder:default:={} + PeerVolumeMounts []corev1.VolumeMount `json:"peerVolumeMounts"` + // +optional // +nullable UpdateCertificateTime *metav1.Time `json:"updateCertificateTime"` diff --git a/api/hlf.kungfusoftware.es/v1alpha1/zz_generated.deepcopy.go b/api/hlf.kungfusoftware.es/v1alpha1/zz_generated.deepcopy.go index 29a8af6a..535121c7 100644 --- a/api/hlf.kungfusoftware.es/v1alpha1/zz_generated.deepcopy.go +++ b/api/hlf.kungfusoftware.es/v1alpha1/zz_generated.deepcopy.go @@ -28,6 +28,21 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddressOverride) DeepCopyInto(out *AddressOverride) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressOverride. +func (in *AddressOverride) DeepCopy() *AddressOverride { + if in == nil { + return nil + } + out := new(AddressOverride) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApplicationCapabilities) DeepCopyInto(out *ApplicationCapabilities) { *out = *in @@ -3340,6 +3355,25 @@ func (in *FabricPeerSpec) DeepCopyInto(out *FabricPeerSpec) { (*out)[key] = val } } + if in.DeliveryClientaddressOverrides != nil { + in, out := &in.DeliveryClientaddressOverrides, &out.DeliveryClientaddressOverrides + *out = make([]AddressOverride, len(*in)) + copy(*out, *in) + } + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]v1.Volume, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.PeerVolumeMounts != nil { + in, out := &in.PeerVolumeMounts, &out.PeerVolumeMounts + *out = make([]v1.VolumeMount, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.UpdateCertificateTime != nil { in, out := &in.UpdateCertificateTime, &out.UpdateCertificateTime *out = (*in).DeepCopy() diff --git a/charts/hlf-peer/templates/configmap--peer--core.yaml b/charts/hlf-peer/templates/configmap--peer--core.yaml index a033f0cf..2f5d5634 100644 --- a/charts/hlf-peer/templates/configmap--peer--core.yaml +++ b/charts/hlf-peer/templates/configmap--peer--core.yaml @@ -358,12 +358,9 @@ data: # A list of orderer endpoint addresses which should be overridden # when found in channel configurations. addressOverrides: - # - from: - # to: - # caCertsFile: - # - from: - # to: - # caCertsFile: + {{- if $.Values.deliveryClientaddressOverrides }} + {{ $.Values.deliveryClientaddressOverrides | toYaml | nindent 10 }} + {{- end }} # Type for the local MSP - by default it's of type bccsp localMspType: bccsp diff --git a/charts/hlf-peer/templates/deployment.yaml b/charts/hlf-peer/templates/deployment.yaml index 5a556f56..5a02a426 100644 --- a/charts/hlf-peer/templates/deployment.yaml +++ b/charts/hlf-peer/templates/deployment.yaml @@ -42,6 +42,10 @@ spec: hostAliases: {{ toYaml .Values.hostAliases | indent 10 }} volumes: +# range through .Values.volumes + {{- if .Values.volumes }} +{{ toYaml .Values.volumes | nindent 8 }} + {{- end }} {{- if eq .Values.peer.databaseType "CouchDB" }} - name: couchdb {{- if and .Values.persistence.couchdb.enabled ( not .Values.couchdb.external.enabled) }} @@ -246,6 +250,10 @@ spec: - configMapRef: name: {{ include "hlf-peer.fullname" . }}--peer volumeMounts: +# range volumeMounts + {{- if .Values.volumeMounts }} +{{ toYaml .Values.peerVolumeMounts | nindent 12 }} + {{- end }} - name: peerconfig mountPath: /var/hyperledger/fabric_cfg - mountPath: /var/hyperledger diff --git a/charts/hlf-peer/values.yaml b/charts/hlf-peer/values.yaml index 40603998..c14f82e9 100644 --- a/charts/hlf-peer/values.yaml +++ b/charts/hlf-peer/values.yaml @@ -118,7 +118,8 @@ resources: memory: 128Mi replicas: 1 nodeSelector: { } - +volumes: [] +peerVolumeMounts: [ ] tolerations: [ ] affinity: { } @@ -164,6 +165,8 @@ logging: externalChaincodeBuilder: false +deliveryClientaddressOverrides: [] + externalBuilders: [ ] proxy: diff --git a/config/crd/bases/hlf.kungfusoftware.es_fabricpeers.yaml b/config/crd/bases/hlf.kungfusoftware.es_fabricpeers.yaml index 677ca1ac..4d90f8a5 100644 --- a/config/crd/bases/hlf.kungfusoftware.es_fabricpeers.yaml +++ b/config/crd/bases/hlf.kungfusoftware.es_fabricpeers.yaml @@ -924,6 +924,22 @@ spec: - tag - user type: object + deliveryClientaddressOverrides: + items: + properties: + caCertsFile: + type: string + from: + type: string + to: + type: string + required: + - caCertsFile + - from + - to + type: object + nullable: true + type: array discovery: properties: period: @@ -1373,6 +1389,45 @@ spec: required: - nodeSelectorTerms type: object + peerVolumeMounts: + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. Behaves similarly to + SubPath but environment variable references $(VAR_NAME) are + expanded using the container's environment. Defaults to "" + (volume's root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + nullable: true + type: array podAnnotations: additionalProperties: type: string @@ -1849,6 +1904,1502 @@ spec: format: date-time nullable: true type: string + volumes: + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition + for /dev/sda is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent disk + resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount on + the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: None, + Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in the + blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the blob + storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single blob + disk per storage account Managed: azure managed data + disk (only in managed availability set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service mount + on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host that + shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is the + path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is empty. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados user name, + default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached and + mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred to + be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should populate + this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. Defaults to + 0644. Directories within the path are not affected by + this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair in + the Data field of the referenced ConfigMap will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in + the ConfigMap, the volume setup will error unless it is + marked optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents ephemeral + storage that is handled by certain external CSI drivers (Beta + feature). + properties: + driver: + description: driver is the name of the CSI driver that handles + this volume. Consult with your admin for the correct name + as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the associated + CSI driver which will determine the default filesystem + to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to the + secret object containing sensitive information to pass + to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the secret + object contains more than one secret, all secret references + are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific properties + that are passed to the CSI driver. Consult your driver's + documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the pod + that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created files + by default. Must be a Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. Defaults to + 0644. Directories within the path are not affected by + this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the pod: + only annotations, labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to set permissions + on this file, must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This might + be in conflict with other options that affect the + file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative path + name of the file to be created. Must not be absolute + or contain the ''..'' path. Must be utf-8 encoded. + The first item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory that + shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which means + to use the node''s default medium. Must be an empty string + (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is also + applicable for memory medium. The maximum usage on memory + medium EmptyDir would be the minimum value between the + SizeLimit specified here and the sum of memory limits + of all containers in a pod. The default is nil which means + that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled + by a cluster storage driver. The volume's lifecycle is tied + to the pod that defines it - it will be created before the + pod starts, and deleted when the pod is removed. \n Use this + if: a) the volume is only needed while the pod runs, b) features + of normal volumes like restoring from snapshot or capacity + \ tracking are needed, c) the storage driver is specified + through a storage class, and d) the storage driver supports + dynamic volume provisioning through a PersistentVolumeClaim + (see EphemeralVolumeSource for more information on the + connection between this volume type and PersistentVolumeClaim). + \n Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the lifecycle + of an individual pod. \n Use CSI for light-weight local ephemeral + volumes if the CSI driver is meant to be used that way - see + the documentation of the driver for more information. \n A + pod can use both types of ephemeral volumes and persistent + volumes at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC to + provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the PVC + will be deleted together with the pod. The name of the + PVC will be `-` where `` is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too long). \n + An existing PVC with that name that is not owned by the + pod will *not* be used for the pod to avoid using an unrelated + volume by mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created PVC + is meant to be used by the pod, the PVC has to updated + with an owner reference to the pod once the pod exists. + Normally this should not be necessary, but it may be useful + when manually reconstructing a broken cluster. \n This + field is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, must + not be nil." + properties: + metadata: + description: May contain labels and annotations that + will be copied into the PVC when creating it. No other + fields are allowed and will be rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the PVC + that gets created from this template. The same fields + as in a PersistentVolumeClaim are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the + provisioner or an external controller can support + the specified data source, it will create a new + volume based on the contents of the specified + data source. If the AnyVolumeDataSource feature + gate is enabled, this field will always have the + same contents as the DataSourceRef field.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object + from which to populate the volume with data, if + a non-empty volume is desired. This may be any + local object from a non-empty API group (non core + object) or a PersistentVolumeClaim object. When + this field is specified, volume binding will only + succeed if the type of the specified object matches + some installed volume populator or dynamic provisioner. + This field will replace the functionality of the + DataSource field and as such if both fields are + non-empty, they must have the same value. For + backwards compatibility, both fields (DataSource + and DataSourceRef) will be set to the same value + automatically if one of them is empty and the + other is non-empty. There are two important differences + between DataSource and DataSourceRef: * While + DataSource only allows two specific types of objects, + DataSourceRef allows any non-core object, as + well as PersistentVolumeClaim objects. * While + DataSource ignores disallowed values (dropping + them), DataSourceRef preserves all values, and + generates an error if a disallowed value is specified. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than previous + value but must still be higher than capacity recorded + in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. If Requests + is omitted for a container, it defaults to + Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes + to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of the + StorageClass required by the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem + is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that is + attached to a kubelet's host machine and then exposed to the + pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. TODO: how do we prevent errors in the + filesystem from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs and + lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use for + this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". The default filesystem depends + on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds extra + command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if no + secret object is specified. If the secret object contains + more than one secret, all secrets are passed to the plugin + scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached to + a kubelet's host machine. This depends on the Flocker control + service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored as + metadata -> name on the dataset for Flocker should be + considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. This + is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume that + you want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: "ext4", + "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition + for /dev/sda is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource in + GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an InitContainer + that clones the repo using git, then mount the EmptyDir into + the Pod''s container.' + properties: + directory: + description: directory is the target directory name. Must + not contain or start with '..'. If '.' is supplied, the + volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More info: + https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs volume + to be mounted with read-only permissions. Defaults to + false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or directory + on the host machine that is directly exposed to the container. + This is generally used for system agents or other privileged + things that are allowed to see the host machine. Most containers + will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host directory + mounts and who can/can not mount host directories as read/write.' + properties: + path: + description: 'path of the directory on the host. If the + path is a symlink, it will follow the link to the real + path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that is + attached to a kubelet''s host machine and then exposed to + the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support iSCSI + Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support iSCSI + Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that uses + an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. The + portal is either an IP or ip_addr:port if the port is + other than default (typically TCP ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI target + and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. The Portal + is either an IP or ip_addr:port if the port is other than + default (typically TCP ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL and unique + within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host that shares + a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. More + info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export to + be mounted with read-only permissions. Defaults to false. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of the + NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents a + reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting in + VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set permissions + on created files by default. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path are + not affected by this setting. This might be in conflict + with other options that affect the file mode, like fsGroup, + and the result can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along with + other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the ConfigMap, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be + an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML + accepts both octal and decimal values, + JSON requires decimal values for mode + bits. If not specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the file + mode, like fsGroup, and the result can + be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' + path. Must be utf-8 encoded. The first + item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and requests + (limits.cpu, limits.memory, requests.cpu + and requests.memory) are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret data + to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the Secret, the volume setup + will error unless it is marked optional. Paths + must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional field specify whether the + Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information about + the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must identify + itself with an identifier specified in the audience + of the token, and otherwise should reject the + token. The audience defaults to the identifier + of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, the + kubelet volume plugin will proactively rotate + the service account token. The kubelet will + start trying to rotate the token if the token + is older than 80 percent of its time to live + or if the token is older than 24 hours.Defaults + to 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is no + group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults to + false. + type: boolean + registry: + description: registry represents a single or multiple Quobyte + Registry services specified as a string as host:port pair + (multiple entries are separated with commas) which acts + as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume in the + Backend Used with dynamically provisioned Quobyte volumes, + value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to serivceaccount + user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication secret + for RBDUser. If provided overrides keyring. Default is + nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for ScaleIO + user and other sensitive information. If this is not provided, + Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage for + a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: system is the name of the storage system as + configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. Defaults to + 0644. Directories within the path are not affected by + this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in + the Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for obtaining + the StorageOS API credentials. If not specified, default + values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name of the + StorageOS volume. Volume names are only unique within + a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of the + volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows the + Kubernetes name scoping to be mirrored within StorageOS + for tighter integration. Set VolumeName to any name to + override the default behaviour. Set to "default" if you + are not using namespaces within StorageOS. Namespaces + that do not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy Based + Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies vSphere + volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + nullable: true + type: array required: - couchdb - discovery diff --git a/controllers/certs/provision_certs.go b/controllers/certs/provision_certs.go index 99099c8b..2d2b96a4 100644 --- a/controllers/certs/provision_certs.go +++ b/controllers/certs/provision_certs.go @@ -365,82 +365,4 @@ func GetClient(ca FabricCAParams) (*lib.Client, error) { return nil, err } return client, err - //m1 := &mockIsSecurityEnabled{} - //m2 := &mockSecurityAlgorithm{} - //m3 := &mockSecurityLevel{} - //m4 := &mockSecurityProvider{} - //m5 := &mockSoftVerify{} - //m6 := &mockSecurityProviderLibPath{} - //m7 := &mockSecurityProviderPin{} - //m8 := &mockSecurityProviderLabel{} - //m9 := &mockKeyStorePath{ - // Path: keyStorePath, - //} - //mspID := ca.MSPID - //fabricConfig, err := getFabricConfig(ca) - //if err != nil { - // return nil, nil, nil, nil, err - //} - //configYaml, err := yaml.Marshal(fabricConfig) - //if err != nil { - // return nil, nil, nil, nil, err - //} - //configBackend, err := config.FromRaw(configYaml, "yaml")() - //if err != nil { - // return nil, nil, nil, nil, err - //} - //cryptSuiteConfig2 := cryptosuite.ConfigFromBackend(configBackend...) - //cryptSuiteConfigOption, err := cryptosuite.BuildCryptoSuiteConfigFromOptions( - // m1, m2, m3, m4, m5, m6, m7, m8, m9, - //) - //if err != nil { - // return nil, nil, nil, nil, err - //} - //cryptSuiteConfig1, ok := cryptSuiteConfigOption.(*cryptosuite.CryptoConfigOptions) - //if !ok { - // return nil, nil, nil, nil, errors.New(fmt.Sprintf("BuildCryptoSuiteConfigFromOptions did not return an Options instance %T", cryptSuiteConfigOption)) - //} - //cryptSuiteConfig := cryptosuite.UpdateMissingOptsWithDefaultConfig(cryptSuiteConfig1, cryptSuiteConfig2) - // - //endpointConfig, err := fabImpl.ConfigFromBackend(configBackend...) - //if err != nil { - // return nil, nil, nil, nil, err - //} - //identityConfig, err := msp.ConfigFromBackend(configBackend...) - //if err != nil { - // return nil, nil, nil, nil, err - //} - //cryptoSuite, err := sw.GetSuiteByConfig(cryptSuiteConfig) - //if err != nil { - // return nil, nil, nil, nil, err - //} - //userStore := msp.NewMemoryUserStore() - //identityManagers := make(map[string]mspprov.IdentityManager) - //netConfig := endpointConfig.NetworkConfig() - //if netConfig == nil { - // panic("failed to get network config") - //} - //for orgName := range netConfig.Organizations { - // mgr, err1 := msp.NewIdentityManager(orgName, userStore, cryptoSuite, endpointConfig) - // if err1 != nil { - // panic(fmt.Sprintf("failed to initialize identity manager for organization: %s, cause :%s", orgName, err1)) - // } - // identityManagers[orgName] = mgr - //} - // - //identityManagerProvider := &identityManagerProvider{identityManager: identityManagers} - //ctxProvider := fabricctx.NewProvider( - // fabricctx.WithIdentityManagerProvider(identityManagerProvider), - // fabricctx.WithUserStore(userStore), - // fabricctx.WithCryptoSuite(cryptoSuite), - // //fabricctx.WithCryptoSuiteConfig(cryptSuiteConfig), - // fabricctx.WithEndpointConfig(endpointConfig), - // fabricctx.WithIdentityConfig(identityConfig), - //) - //fctx := &fabricctx.Client{Providers: ctxProvider} - //client, err := msp.NewCAClient(mspID, fctx) - //if err != nil { - // return nil, nil, nil, nil, err - //} - //return client, userStore, identityManagers, cryptoSuite, nil } diff --git a/controllers/followerchannel/followerchannel_controller.go b/controllers/followerchannel/followerchannel_controller.go index 3edbf488..47253812 100644 --- a/controllers/followerchannel/followerchannel_controller.go +++ b/controllers/followerchannel/followerchannel_controller.go @@ -134,6 +134,7 @@ func (r *FabricFollowerChannelReconciler) Reconcile(ctx context.Context, req ctr r.setConditionStatus(ctx, fabricFollowerChannel, hlfv1alpha1.FailedStatus, false, err, false) return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricFollowerChannel) } + defer sdk.Close() idConfig := fabricFollowerChannel.Spec.HLFIdentity secret, err := clientSet.CoreV1().Secrets(idConfig.SecretNamespace).Get(ctx, idConfig.SecretName, v1.GetOptions{}) if err != nil { @@ -359,15 +360,14 @@ func (r *FabricFollowerChannelReconciler) Reconcile(ctx context.Context, req ctr fabricFollowerChannel.Status.Status = hlfv1alpha1.RunningStatus fabricFollowerChannel.Status.Message = "Peers and anchor peers completed" fabricFollowerChannel.Status.Conditions.SetCondition(status.Condition{ - Type: "CREATED", - Status: "True", - LastTransitionTime: v1.Time{}, + Type: status.ConditionType(fabricFollowerChannel.Status.Status), + Status: "True", }) if err := r.Status().Update(ctx, fabricFollowerChannel); err != nil { r.setConditionStatus(ctx, fabricFollowerChannel, hlfv1alpha1.FailedStatus, false, err, false) return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricFollowerChannel) } - return ctrl.Result{}, nil + return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricFollowerChannel) } var ( diff --git a/controllers/identity/identity_controller.go b/controllers/identity/identity_controller.go index 4ace7440..6b476b59 100644 --- a/controllers/identity/identity_controller.go +++ b/controllers/identity/identity_controller.go @@ -22,6 +22,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -52,7 +53,25 @@ func (r *FabricIdentityReconciler) finalizeMainChannel(reqLogger logr.Logger, m return nil } - +func getCertBytesFromCATLS(client *kubernetes.Clientset, caTls hlfv1alpha1.Catls) ([]byte, error) { + var signCertBytes []byte + var err error + if caTls.Cacert != "" { + signCertBytes, err = base64.StdEncoding.DecodeString(caTls.Cacert) + if err != nil { + return nil, err + } + } else if caTls.SecretRef != nil { + secret, err := client.CoreV1().Secrets(caTls.SecretRef.Namespace).Get(context.Background(), caTls.SecretRef.Name, v1.GetOptions{}) + if err != nil { + return nil, err + } + signCertBytes = secret.Data[caTls.SecretRef.Key] + } else { + return nil, errors.New("invalid ca tls") + } + return signCertBytes, nil +} func (r *FabricIdentityReconciler) addFinalizer(reqLogger logr.Logger, m *hlfv1alpha1.FabricIdentity) error { reqLogger.Info("Adding Finalizer for the MainChannel") controllerutil.AddFinalizer(m, identityFinalizer) @@ -108,7 +127,7 @@ func (r *FabricIdentityReconciler) Reconcile(ctx context.Context, req ctrl.Reque r.setConditionStatus(ctx, fabricIdentity, hlfv1alpha1.FailedStatus, false, err, false) return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricIdentity) } - tlsCert, err := base64.StdEncoding.DecodeString(fabricIdentity.Spec.Catls.Cacert) + tlsCert, err := getCertBytesFromCATLS(clientSet, fabricIdentity.Spec.Catls) if err != nil { r.setConditionStatus(ctx, fabricIdentity, hlfv1alpha1.FailedStatus, false, err, false) return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricIdentity) @@ -275,7 +294,7 @@ func (r *FabricIdentityReconciler) Reconcile(ctx context.Context, req ctrl.Reque fabricIdentity.Status.Status = hlfv1alpha1.RunningStatus fabricIdentity.Status.Message = "Identity Setup" fabricIdentity.Status.Conditions.SetCondition(status.Condition{ - Type: "CREATED", + Type: status.ConditionType(fabricIdentity.Status.Status), Status: "True", LastTransitionTime: v1.Time{}, }) diff --git a/controllers/mainchannel/mainchannel_controller.go b/controllers/mainchannel/mainchannel_controller.go index 4bbfac2a..600cece9 100644 --- a/controllers/mainchannel/mainchannel_controller.go +++ b/controllers/mainchannel/mainchannel_controller.go @@ -145,6 +145,7 @@ func (r *FabricMainChannelReconciler) Reconcile(ctx context.Context, req ctrl.Re r.setConditionStatus(ctx, fabricMainChannel, hlfv1alpha1.FailedStatus, false, err, false) return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricMainChannel) } + defer sdk.Close() firstAdminOrgMSPID := fabricMainChannel.Spec.AdminPeerOrganizations[0].MSPID idConfig, ok := fabricMainChannel.Spec.Identities[firstAdminOrgMSPID] if !ok { @@ -268,10 +269,15 @@ func (r *FabricMainChannelReconciler) Reconcile(ctx context.Context, req ctrl.Re r.setConditionStatus(ctx, fabricMainChannel, hlfv1alpha1.FailedStatus, false, fmt.Errorf("couldn't append certs from org %s", ordererOrg.MSPID), false) return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricMainChannel) } - idConfig, ok := fabricMainChannel.Spec.Identities[ordererOrg.MSPID] + idConfig, ok := fabricMainChannel.Spec.Identities[fmt.Sprintf("%s-tls", ordererOrg.MSPID)] if !ok { - r.setConditionStatus(ctx, fabricMainChannel, hlfv1alpha1.FailedStatus, false, fmt.Errorf("identity not found for MSPID %s", ordererOrg.MSPID), false) - return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricMainChannel) + log.Infof("Identity for MSPID %s not found, trying with normal identity", fmt.Sprintf("%s-tls", ordererOrg.MSPID)) + // try with normal identity + idConfig, ok = fabricMainChannel.Spec.Identities[ordererOrg.MSPID] + if !ok { + r.setConditionStatus(ctx, fabricMainChannel, hlfv1alpha1.FailedStatus, false, fmt.Errorf("identity not found for MSPID %s", ordererOrg.MSPID), false) + return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricMainChannel) + } } secret, err := clientSet.CoreV1().Secrets(idConfig.SecretNamespace).Get(ctx, idConfig.SecretName, v1.GetOptions{}) if err != nil { @@ -737,18 +743,15 @@ func (r *FabricMainChannelReconciler) Reconcile(ctx context.Context, req ctrl.Re fabricMainChannel.Status.Message = "Channel setup completed" fabricMainChannel.Status.Conditions.SetCondition(status.Condition{ - Type: "CREATED", - Status: "True", - LastTransitionTime: v1.Time{}, + Type: status.ConditionType(fabricMainChannel.Status.Status), + Status: "True", }) if err := r.Status().Update(ctx, fabricMainChannel); err != nil { r.setConditionStatus(ctx, fabricMainChannel, hlfv1alpha1.FailedStatus, false, err, false) return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricMainChannel) } - return ctrl.Result{ - Requeue: false, - RequeueAfter: 0, - }, nil + r.setConditionStatus(ctx, fabricMainChannel, hlfv1alpha1.RunningStatus, true, nil, false) + return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricMainChannel) } var ( diff --git a/controllers/networkconfig/networkconfig_controller.go b/controllers/networkconfig/networkconfig_controller.go index 28d5f78e..f0eda2d6 100644 --- a/controllers/networkconfig/networkconfig_controller.go +++ b/controllers/networkconfig/networkconfig_controller.go @@ -471,13 +471,16 @@ func (r *FabricNetworkConfigReconciler) Reconcile(ctx context.Context, req ctrl. r.setConditionStatus(ctx, fabricNetworkConfig, hlfv1alpha1.RunningStatus, true, nil, false) fca := fabricNetworkConfig.DeepCopy() fca.Status.Status = hlfv1alpha1.RunningStatus + fca.Status.Conditions.SetCondition(status.Condition{ + Type: status.ConditionType(fca.Status.Status), + Status: "True", + }) if err := r.Status().Update(ctx, fca); err != nil { log.Error(err, fmt.Sprintf("%v failed to update the application status", ErrClientK8s)) return reconcile.Result{}, err } - return ctrl.Result{ - RequeueAfter: 1 * time.Minute, - }, nil + r.setConditionStatus(ctx, fabricNetworkConfig, hlfv1alpha1.RunningStatus, true, nil, false) + return r.updateCRStatusOrFailReconcileWithRequeue(ctx, r.Log, fabricNetworkConfig, 1*time.Minute) } var ( @@ -492,6 +495,16 @@ func (r *FabricNetworkConfigReconciler) updateCRStatusOrFailReconcile(ctx contex } return reconcile.Result{}, nil } +func (r *FabricNetworkConfigReconciler) updateCRStatusOrFailReconcileWithRequeue(ctx context.Context, log logr.Logger, p *hlfv1alpha1.FabricNetworkConfig, requeueAfter time.Duration) ( + reconcile.Result, error) { + if err := r.Status().Update(ctx, p); err != nil { + log.Error(err, fmt.Sprintf("%v failed to update the application status", ErrClientK8s)) + return reconcile.Result{}, err + } + return reconcile.Result{ + RequeueAfter: requeueAfter, + }, nil +} func (r *FabricNetworkConfigReconciler) setConditionStatus(ctx context.Context, p *hlfv1alpha1.FabricNetworkConfig, conditionType hlfv1alpha1.DeploymentStatus, statusFlag bool, err error, statusUnknown bool) (update bool) { statusStr := func() corev1.ConditionStatus { diff --git a/controllers/peer/peer_controller.go b/controllers/peer/peer_controller.go index 39bae84c..d743d152 100644 --- a/controllers/peer/peer_controller.go +++ b/controllers/peer/peer_controller.go @@ -1393,14 +1393,17 @@ func GetConfig( Proxy: spec.Resources.Proxy, } var c = FabricPeerChart{ - PodLabels: spec.PodLabels, - PodAnnotations: spec.PodAnnotations, - EnvVars: spec.Env, - Replicas: spec.Replicas, - ImagePullSecrets: spec.ImagePullSecrets, - GatewayApi: gatewayApi, - Istio: istio, - Traefik: traefik, + DeliveryClientaddressOverrides: spec.DeliveryClientaddressOverrides, + Volumes: spec.Volumes, + PeerVolumeMounts: spec.PeerVolumeMounts, + PodLabels: spec.PodLabels, + PodAnnotations: spec.PodAnnotations, + EnvVars: spec.Env, + Replicas: spec.Replicas, + ImagePullSecrets: spec.ImagePullSecrets, + GatewayApi: gatewayApi, + Istio: istio, + Traefik: traefik, Image: Image{ Repository: spec.Image, Tag: spec.Tag, diff --git a/controllers/peer/types.go b/controllers/peer/types.go index 0af6a5b5..753a3494 100644 --- a/controllers/peer/types.go +++ b/controllers/peer/types.go @@ -1,6 +1,9 @@ package peer -import corev1 "k8s.io/api/core/v1" +import ( + v1alpha1 "github.com/kfsoftware/hlf-operator/api/hlf.kungfusoftware.es/v1alpha1" + corev1 "k8s.io/api/core/v1" +) type RBAC struct { Ns string `json:"ns"` @@ -23,45 +26,49 @@ type FSServer struct { } type FabricPeerChart struct { - PodLabels map[string]string `json:"podLabels"` - PodAnnotations map[string]string `json:"podAnnotations"` - FSServer FSServer `json:"fsServer"` - GatewayApi GatewayApi `json:"gatewayApi"` - Istio Istio `json:"istio"` - Traefik Traefik `json:"traefik"` - Replicas int `json:"replicas"` - ExternalChaincodeBuilder bool `json:"externalChaincodeBuilder"` - CouchdbUsername string `json:"couchdbUsername"` - CouchdbPassword string `json:"couchdbPassword"` - Image Image `json:"image"` - CouchDB CouchDB `json:"couchdb"` - Rbac RBAC `json:"rbac"` - DockerSocketPath string `json:"dockerSocketPath"` - Peer Peer `json:"peer"` - Cert string `json:"cert"` - Key string `json:"key"` - Hosts []string `json:"hosts"` - Proxy GRPCProxy `json:"proxy"` - TLS TLS `json:"tls"` - OPSTLS TLS `json:"opsTLS"` - Cacert string `json:"cacert"` - IntCacert string `json:"intCAcert"` - Tlsrootcert string `json:"tlsrootcert"` - Resources PeerResources `json:"resources,omitempty"` - NodeSelector *corev1.NodeSelector `json:"nodeSelector,omitempty"` - Tolerations []corev1.Toleration `json:"tolerations,omitempty"` - ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets"` - Affinity *corev1.Affinity `json:"affinity,omitempty"` - ExternalHost string `json:"externalHost"` - FullnameOverride string `json:"fullnameOverride"` - CouchDBExporter CouchDBExporter `json:"couchdbExporter"` - HostAliases []HostAlias `json:"hostAliases"` - Service Service `json:"service"` - Persistence PeerPersistence `json:"persistence"` - Logging Logging `json:"logging"` - ExternalBuilders []ExternalBuilder `json:"externalBuilders"` - ServiceMonitor ServiceMonitor `json:"serviceMonitor"` - EnvVars []corev1.EnvVar `json:"envVars"` + Volumes []corev1.Volume `json:"volumes"` + PeerVolumeMounts []corev1.VolumeMount `json:"peerVolumeMounts"` + + PodLabels map[string]string `json:"podLabels"` + PodAnnotations map[string]string `json:"podAnnotations"` + FSServer FSServer `json:"fsServer"` + GatewayApi GatewayApi `json:"gatewayApi"` + Istio Istio `json:"istio"` + Traefik Traefik `json:"traefik"` + Replicas int `json:"replicas"` + ExternalChaincodeBuilder bool `json:"externalChaincodeBuilder"` + CouchdbUsername string `json:"couchdbUsername"` + CouchdbPassword string `json:"couchdbPassword"` + Image Image `json:"image"` + CouchDB CouchDB `json:"couchdb"` + Rbac RBAC `json:"rbac"` + DockerSocketPath string `json:"dockerSocketPath"` + Peer Peer `json:"peer"` + Cert string `json:"cert"` + Key string `json:"key"` + Hosts []string `json:"hosts"` + Proxy GRPCProxy `json:"proxy"` + TLS TLS `json:"tls"` + OPSTLS TLS `json:"opsTLS"` + Cacert string `json:"cacert"` + IntCacert string `json:"intCAcert"` + Tlsrootcert string `json:"tlsrootcert"` + Resources PeerResources `json:"resources,omitempty"` + NodeSelector *corev1.NodeSelector `json:"nodeSelector,omitempty"` + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets"` + Affinity *corev1.Affinity `json:"affinity,omitempty"` + ExternalHost string `json:"externalHost"` + FullnameOverride string `json:"fullnameOverride"` + CouchDBExporter CouchDBExporter `json:"couchdbExporter"` + HostAliases []HostAlias `json:"hostAliases"` + Service Service `json:"service"` + Persistence PeerPersistence `json:"persistence"` + Logging Logging `json:"logging"` + ExternalBuilders []ExternalBuilder `json:"externalBuilders"` + ServiceMonitor ServiceMonitor `json:"serviceMonitor"` + EnvVars []corev1.EnvVar `json:"envVars"` + DeliveryClientaddressOverrides []v1alpha1.AddressOverride `json:"deliveryClientaddressOverrides"` } type GatewayApi struct { Port int `json:"port"` diff --git a/kubectl-hlf/cmd/chaincode/invoke.go b/kubectl-hlf/cmd/chaincode/invoke.go index 096d609c..76522d8f 100644 --- a/kubectl-hlf/cmd/chaincode/invoke.go +++ b/kubectl-hlf/cmd/chaincode/invoke.go @@ -3,6 +3,7 @@ package chaincode import ( "fmt" "github.com/hyperledger/fabric-sdk-go/pkg/client/channel" + "github.com/hyperledger/fabric-sdk-go/pkg/common/logging" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" "github.com/kfsoftware/hlf-operator/kubectl-hlf/cmd/helpers" @@ -78,6 +79,7 @@ func (c *invokeChaincodeCmd) run(out io.Writer) error { return nil } func newInvokeChaincodeCMD(out io.Writer, errOut io.Writer) *cobra.Command { + logging.Initialize(helpers.HLFLoggerProvider{}) c := &invokeChaincodeCmd{} cmd := &cobra.Command{ Use: "invoke", diff --git a/kubectl-hlf/cmd/channel/inspect.go b/kubectl-hlf/cmd/channel/inspect.go index 82e16990..ab3ecc33 100644 --- a/kubectl-hlf/cmd/channel/inspect.go +++ b/kubectl-hlf/cmd/channel/inspect.go @@ -8,11 +8,9 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/fab/resource" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" "github.com/hyperledger/fabric/common/tools/protolator" - "github.com/hyperledger/fabric/protoutil" "github.com/kfsoftware/hlf-operator/kubectl-hlf/cmd/helpers" "github.com/spf13/cobra" "io" - "io/ioutil" ) type inspectChannelCmd struct { @@ -58,7 +56,6 @@ func (c *inspectChannelCmd) run(out io.Writer) error { if err != nil { return err } - ioutil.WriteFile("block.pb", protoutil.MarshalOrPanic(block), 0644) cmnConfig, err := resource.ExtractConfigFromBlock(block) if err != nil { return err diff --git a/kubectl-hlf/cmd/helpers/hlfLogger.go b/kubectl-hlf/cmd/helpers/hlfLogger.go new file mode 100644 index 00000000..33dc1033 --- /dev/null +++ b/kubectl-hlf/cmd/helpers/hlfLogger.go @@ -0,0 +1,96 @@ +package helpers + +import "github.com/hyperledger/fabric-sdk-go/pkg/core/logging/api" + +type hlfLogger struct { +} + +func (f hlfLogger) Fatal(v ...interface{}) { + // do nothing +} + +func (f hlfLogger) Fatalf(format string, v ...interface{}) { + // do nothing +} + +func (f hlfLogger) Fatalln(v ...interface{}) { + // do nothing +} + +func (f hlfLogger) Panic(v ...interface{}) { + // do nothing +} + +func (f hlfLogger) Panicf(format string, v ...interface{}) { + // do nothing +} + +func (f hlfLogger) Panicln(v ...interface{}) { + // do nothing +} + +func (f hlfLogger) Print(v ...interface{}) { + // do nothing +} + +func (f hlfLogger) Printf(format string, v ...interface{}) { + // do nothing +} + +func (f hlfLogger) Println(v ...interface{}) { + // do nothing +} + +func (f hlfLogger) Debug(args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Debugf(format string, args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Debugln(args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Info(args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Infof(format string, args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Infoln(args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Warn(args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Warnf(format string, args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Warnln(args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Error(args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Errorf(format string, args ...interface{}) { + // do nothing +} + +func (f hlfLogger) Errorln(args ...interface{}) { + // do nothing +} + +type HLFLoggerProvider struct{} + +func (f HLFLoggerProvider) GetLogger(module string) api.Logger { + return hlfLogger{} +} diff --git a/kubectl-hlf/cmd/identity/create.go b/kubectl-hlf/cmd/identity/create.go index 4cfb04cb..2afd021b 100644 --- a/kubectl-hlf/cmd/identity/create.go +++ b/kubectl-hlf/cmd/identity/create.go @@ -11,14 +11,17 @@ import ( ) type createIdentityCmd struct { - name string - namespace string - caName string - caNamespace string - ca string - mspID string - enrollId string - enrollSecret string + name string + namespace string + caName string + caNamespace string + ca string + mspID string + enrollId string + enrollSecret string + caEnrollId string + caEnrollSecret string + caType string } func (c *createIdentityCmd) validate() error { @@ -78,6 +81,16 @@ func (c *createIdentityCmd) run() error { Enrollsecret: c.enrollSecret, MSPID: c.mspID, } + if c.caEnrollId != "" && c.caEnrollSecret != "" { + fabricIdentitySpec.Register = &v1alpha1.FabricIdentityRegister{ + Enrollid: c.caEnrollId, + Enrollsecret: c.caEnrollSecret, + Type: c.caType, + Affiliation: "", + MaxEnrollments: -1, + Attrs: []string{}, + } + } fabricIdentity := &v1alpha1.FabricIdentity{ ObjectMeta: v1.ObjectMeta{ Name: c.name, @@ -121,5 +134,8 @@ func newIdentityCreateCMD() *cobra.Command { f.StringVar(&c.mspID, "mspid", "", "MSP ID") f.StringVar(&c.enrollId, "enroll-id", "", "Enroll ID") f.StringVar(&c.enrollSecret, "enroll-secret", "", "Enroll Secret") + f.StringVar(&c.caEnrollId, "ca-enroll-id", "", "CA Enroll ID to register the user") + f.StringVar(&c.caEnrollSecret, "ca-enroll-secret", "", "CA Enroll Secret to register the user") + f.StringVar(&c.caType, "ca-type", "", "Type of the user to be registered in the CA") return cmd }