|
| 1 | +package resource |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "fmt" |
| 6 | + "strings" |
| 7 | + |
| 8 | + corev1 "k8s.io/api/core/v1" |
| 9 | + "k8s.io/apimachinery/pkg/api/errors" |
| 10 | + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| 11 | + "k8s.io/apimachinery/pkg/runtime" |
| 12 | + coreset "k8s.io/client-go/kubernetes/typed/core/v1" |
| 13 | + corelisters "k8s.io/client-go/listers/core/v1" |
| 14 | + restclient "k8s.io/client-go/rest" |
| 15 | + "k8s.io/klog/v2" |
| 16 | + |
| 17 | + operatorv1 "github.com/openshift/api/operator/v1" |
| 18 | + configlisters "github.com/openshift/client-go/config/listers/config/v1" |
| 19 | + imageregistryv1listers "github.com/openshift/client-go/imageregistry/listers/imageregistry/v1" |
| 20 | + |
| 21 | + "github.com/openshift/cluster-image-registry-operator/pkg/client" |
| 22 | + "github.com/openshift/cluster-image-registry-operator/pkg/defaults" |
| 23 | + "github.com/openshift/cluster-image-registry-operator/pkg/storage" |
| 24 | +) |
| 25 | + |
| 26 | +var _ Mutator = &generatorImageRegistryCA{} |
| 27 | + |
| 28 | +type generatorImageRegistryCA struct { |
| 29 | + lister corelisters.ConfigMapNamespaceLister |
| 30 | + managedLister corelisters.ConfigMapLister |
| 31 | + imageConfigLister configlisters.ImageLister |
| 32 | + openshiftConfigLister corelisters.ConfigMapNamespaceLister |
| 33 | + serviceLister corelisters.ServiceNamespaceLister |
| 34 | + imageRegistryConfigLister imageregistryv1listers.ConfigLister |
| 35 | + storageListers *client.StorageListers |
| 36 | + kubeconfig *restclient.Config |
| 37 | + client coreset.CoreV1Interface |
| 38 | +} |
| 39 | + |
| 40 | +func NewGeneratorImageRegistryCA( |
| 41 | + lister corelisters.ConfigMapNamespaceLister, |
| 42 | + managedLister corelisters.ConfigMapLister, |
| 43 | + imageConfigLister configlisters.ImageLister, |
| 44 | + openshiftConfigLister corelisters.ConfigMapNamespaceLister, |
| 45 | + serviceLister corelisters.ServiceNamespaceLister, |
| 46 | + imageRegistryConfigLister imageregistryv1listers.ConfigLister, |
| 47 | + storageListers *client.StorageListers, |
| 48 | + kubeconfig *restclient.Config, |
| 49 | + client coreset.CoreV1Interface, |
| 50 | +) Mutator { |
| 51 | + return &generatorImageRegistryCA{ |
| 52 | + lister: lister, |
| 53 | + managedLister: managedLister, |
| 54 | + imageConfigLister: imageConfigLister, |
| 55 | + openshiftConfigLister: openshiftConfigLister, |
| 56 | + serviceLister: serviceLister, |
| 57 | + imageRegistryConfigLister: imageRegistryConfigLister, |
| 58 | + storageListers: storageListers, |
| 59 | + kubeconfig: kubeconfig, |
| 60 | + client: client, |
| 61 | + } |
| 62 | +} |
| 63 | + |
| 64 | +func (girca *generatorImageRegistryCA) Type() runtime.Object { |
| 65 | + return &corev1.ConfigMap{} |
| 66 | +} |
| 67 | + |
| 68 | +func (girca *generatorImageRegistryCA) GetNamespace() string { |
| 69 | + return defaults.OpenShiftConfigManagedNamespace |
| 70 | +} |
| 71 | + |
| 72 | +func (girca *generatorImageRegistryCA) GetName() string { |
| 73 | + return defaults.ImageRegistryCAName |
| 74 | +} |
| 75 | + |
| 76 | +func (girca *generatorImageRegistryCA) storageDriver() (storage.Driver, bool, error) { |
| 77 | + imageRegistryConfig, err := girca.imageRegistryConfigLister.Get("cluster") |
| 78 | + if errors.IsNotFound(err) { |
| 79 | + return nil, false, nil |
| 80 | + } else if err != nil { |
| 81 | + return nil, false, err |
| 82 | + } |
| 83 | + |
| 84 | + if imageRegistryConfig.Spec.ManagementState == operatorv1.Removed { |
| 85 | + // The certificates controller does not need to know about |
| 86 | + // storage when the management state is Removed. |
| 87 | + return nil, false, nil |
| 88 | + } |
| 89 | + |
| 90 | + driver, err := storage.NewDriver(&imageRegistryConfig.Spec.Storage, girca.kubeconfig, girca.storageListers) |
| 91 | + if err == storage.ErrStorageNotConfigured || storage.IsMultiStoragesError(err) { |
| 92 | + return nil, false, nil |
| 93 | + } else if err != nil { |
| 94 | + return nil, false, err |
| 95 | + } |
| 96 | + |
| 97 | + canRedirect := !imageRegistryConfig.Spec.DisableRedirect |
| 98 | + |
| 99 | + return driver, canRedirect, nil |
| 100 | +} |
| 101 | + |
| 102 | +func (girca *generatorImageRegistryCA) expected() (runtime.Object, error) { |
| 103 | + cm := &corev1.ConfigMap{ |
| 104 | + ObjectMeta: metav1.ObjectMeta{ |
| 105 | + Name: girca.GetName(), |
| 106 | + Namespace: girca.GetNamespace(), |
| 107 | + }, |
| 108 | + Data: map[string]string{}, |
| 109 | + BinaryData: map[string][]byte{}, |
| 110 | + } |
| 111 | + |
| 112 | + var ownHostnameKeys []string |
| 113 | + |
| 114 | + serviceCA, err := girca.lister.Get(defaults.ServiceCAName) |
| 115 | + if errors.IsNotFound(err) { |
| 116 | + klog.V(4).Infof("missing the service CA configmap: %s", err) |
| 117 | + } else if err != nil { |
| 118 | + return cm, fmt.Errorf("%s: %s", girca.GetName(), err) |
| 119 | + } else { |
| 120 | + if cert, ok := serviceCA.Data["service-ca.crt"]; ok { |
| 121 | + internalHostnames, err := getServiceHostnames(girca.serviceLister, defaults.ServiceName) |
| 122 | + if err != nil { |
| 123 | + return cm, fmt.Errorf("%s: %s", girca.GetName(), err) |
| 124 | + } |
| 125 | + if len(internalHostnames) == 0 { |
| 126 | + klog.Infof("unable to get the service name to add service-ca.crt") |
| 127 | + } else { |
| 128 | + for _, internalHostname := range internalHostnames { |
| 129 | + key := strings.Replace(internalHostname, ":", "..", -1) |
| 130 | + ownHostnameKeys = append(ownHostnameKeys, key) |
| 131 | + cm.Data[key] = cert |
| 132 | + } |
| 133 | + } |
| 134 | + } else { |
| 135 | + klog.Infof("the service CA is not injected yet") |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + driver, canRedirect, err := girca.storageDriver() |
| 140 | + if err != nil { |
| 141 | + return cm, fmt.Errorf("%s: %s", girca.GetName(), err) |
| 142 | + } |
| 143 | + if driver != nil { |
| 144 | + storageCABundle, _, err := driver.CABundle() |
| 145 | + if err != nil { |
| 146 | + return cm, fmt.Errorf("%s: %s", girca.GetName(), err) |
| 147 | + } |
| 148 | + if storageCABundle != "" { |
| 149 | + klog.V(4).Infof("using storage ca bundle (%d bytes)", len(storageCABundle)) |
| 150 | + if canRedirect { |
| 151 | + klog.V(4).Infof("injecting storage ca bundle into registry certificates...") |
| 152 | + for _, key := range ownHostnameKeys { |
| 153 | + cm.Data[key] += "\n" + storageCABundle |
| 154 | + } |
| 155 | + } |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + return cm, nil |
| 160 | +} |
| 161 | + |
| 162 | +func (girca *generatorImageRegistryCA) Get() (runtime.Object, error) { |
| 163 | + return girca.managedLister.ConfigMaps(defaults.OpenShiftConfigManagedNamespace).Get(girca.GetName()) |
| 164 | +} |
| 165 | + |
| 166 | +func (girca *generatorImageRegistryCA) Create() (runtime.Object, error) { |
| 167 | + return commonCreate(girca, func(obj runtime.Object) (runtime.Object, error) { |
| 168 | + return girca.client.ConfigMaps(girca.GetNamespace()).Create( |
| 169 | + context.TODO(), obj.(*corev1.ConfigMap), metav1.CreateOptions{}, |
| 170 | + ) |
| 171 | + }) |
| 172 | +} |
| 173 | + |
| 174 | +func (girca *generatorImageRegistryCA) Update(o runtime.Object) (runtime.Object, bool, error) { |
| 175 | + return commonUpdate(girca, o, func(obj runtime.Object) (runtime.Object, error) { |
| 176 | + return girca.client.ConfigMaps(girca.GetNamespace()).Update( |
| 177 | + context.TODO(), obj.(*corev1.ConfigMap), metav1.UpdateOptions{}, |
| 178 | + ) |
| 179 | + }) |
| 180 | +} |
| 181 | + |
| 182 | +func (girca *generatorImageRegistryCA) Delete(opts metav1.DeleteOptions) error { |
| 183 | + return girca.client.ConfigMaps(girca.GetNamespace()).Delete( |
| 184 | + context.TODO(), girca.GetName(), opts, |
| 185 | + ) |
| 186 | +} |
| 187 | + |
| 188 | +func (g *generatorImageRegistryCA) Owned() bool { |
| 189 | + return true |
| 190 | +} |
0 commit comments