github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/domain/infra/abi/generate.go (about) 1 package abi 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "strings" 8 9 "github.com/hanks177/podman/v4/libpod" 10 "github.com/hanks177/podman/v4/libpod/define" 11 "github.com/hanks177/podman/v4/pkg/domain/entities" 12 k8sAPI "github.com/hanks177/podman/v4/pkg/k8s.io/api/core/v1" 13 "github.com/hanks177/podman/v4/pkg/systemd/generate" 14 "github.com/ghodss/yaml" 15 "github.com/pkg/errors" 16 ) 17 18 func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, options entities.GenerateSystemdOptions) (*entities.GenerateSystemdReport, error) { 19 // First assume it's a container. 20 ctr, ctrErr := ic.Libpod.LookupContainer(nameOrID) 21 if ctrErr == nil { 22 // Generate the unit for the container. 23 name, content, err := generate.ContainerUnit(ctr, options) 24 if err != nil { 25 return nil, err 26 } 27 return &entities.GenerateSystemdReport{Units: map[string]string{name: content}}, nil 28 } 29 30 // If it's not a container, we either have a pod or garbage. 31 pod, err := ic.Libpod.LookupPod(nameOrID) 32 if err != nil { 33 err = errors.Wrap(ctrErr, err.Error()) 34 return nil, errors.Wrapf(err, "%s does not refer to a container or pod", nameOrID) 35 } 36 37 // Generate the units for the pod and all its containers. 38 units, err := generate.PodUnits(pod, options) 39 if err != nil { 40 return nil, err 41 } 42 return &entities.GenerateSystemdReport{Units: units}, nil 43 } 44 45 func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) { 46 var ( 47 pods []*libpod.Pod 48 ctrs []*libpod.Container 49 vols []*libpod.Volume 50 podContent [][]byte 51 content [][]byte 52 ) 53 54 // Lookup for podman objects. 55 for _, nameOrID := range nameOrIDs { 56 // Let's assume it's a container, so get the container. 57 ctr, err := ic.Libpod.LookupContainer(nameOrID) 58 if err != nil { 59 if !strings.Contains(err.Error(), "no such container") { 60 return nil, err 61 } 62 } else { 63 // now that infra holds NS data, we need to support dependencies. 64 // we cannot deal with ctrs already in a pod. 65 if len(ctr.PodID()) > 0 { 66 return nil, errors.Errorf("container %s is associated with pod %s: use generate on the pod itself", ctr.ID(), ctr.PodID()) 67 } 68 ctrs = append(ctrs, ctr) 69 continue 70 } 71 72 // Maybe it's a pod. 73 pod, err := ic.Libpod.LookupPod(nameOrID) 74 if err != nil { 75 if !strings.Contains(err.Error(), "no such pod") { 76 return nil, err 77 } 78 } else { 79 pods = append(pods, pod) 80 continue 81 } 82 83 // Or volume. 84 vol, err := ic.Libpod.LookupVolume(nameOrID) 85 if err != nil { 86 if !strings.Contains(err.Error(), "no such volume") { 87 return nil, err 88 } 89 } else { 90 vols = append(vols, vol) 91 continue 92 } 93 94 // If it reaches here is because the name or id did not exist. 95 return nil, errors.Errorf("Name or ID %q not found", nameOrID) 96 } 97 98 // Generate kube persistent volume claims from volumes. 99 if len(vols) >= 1 { 100 pvs, err := getKubePVCs(vols) 101 if err != nil { 102 return nil, err 103 } 104 105 content = append(content, pvs...) 106 } 107 108 // Generate kube pods and services from pods. 109 if len(pods) >= 1 { 110 pos, svcs, err := getKubePods(ctx, pods, options.Service) 111 if err != nil { 112 return nil, err 113 } 114 115 podContent = append(podContent, pos...) 116 if options.Service { 117 content = append(content, svcs...) 118 } 119 } 120 121 // Generate the kube pods from containers. 122 if len(ctrs) >= 1 { 123 po, err := libpod.GenerateForKube(ctx, ctrs) 124 if err != nil { 125 return nil, err 126 } 127 if len(po.Spec.Volumes) != 0 { 128 warning := ` 129 # NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux 130 # enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container 131 # has the right permissions to access the volumes added. 132 ` 133 content = append(content, []byte(warning)) 134 } 135 b, err := generateKubeYAML(libpod.ConvertV1PodToYAMLPod(po)) 136 if err != nil { 137 return nil, err 138 } 139 140 podContent = append(podContent, b) 141 if options.Service { 142 svc, err := libpod.GenerateKubeServiceFromV1Pod(po, []k8sAPI.ServicePort{}) 143 if err != nil { 144 return nil, err 145 } 146 b, err := generateKubeYAML(svc) 147 if err != nil { 148 return nil, err 149 } 150 content = append(content, b) 151 } 152 } 153 154 // Content order is based on helm install order (secret, persistentVolumeClaim, service, pod). 155 content = append(content, podContent...) 156 157 // Generate kube YAML file from all kube kinds. 158 k, err := generateKubeOutput(content) 159 if err != nil { 160 return nil, err 161 } 162 163 return &entities.GenerateKubeReport{Reader: bytes.NewReader(k)}, nil 164 } 165 166 // getKubePods returns kube pod and service YAML files from podman pods. 167 func getKubePods(ctx context.Context, pods []*libpod.Pod, getService bool) ([][]byte, [][]byte, error) { 168 pos := [][]byte{} 169 svcs := [][]byte{} 170 171 for _, p := range pods { 172 po, sp, err := p.GenerateForKube(ctx) 173 if err != nil { 174 return nil, nil, err 175 } 176 177 b, err := generateKubeYAML(po) 178 if err != nil { 179 return nil, nil, err 180 } 181 pos = append(pos, b) 182 183 if getService { 184 svc, err := libpod.GenerateKubeServiceFromV1Pod(po, sp) 185 if err != nil { 186 return nil, nil, err 187 } 188 b, err := generateKubeYAML(svc) 189 if err != nil { 190 return nil, nil, err 191 } 192 svcs = append(svcs, b) 193 } 194 } 195 196 return pos, svcs, nil 197 } 198 199 // getKubePVCs returns kube persistent volume claim YAML files from podman volumes. 200 func getKubePVCs(volumes []*libpod.Volume) ([][]byte, error) { 201 pvs := [][]byte{} 202 203 for _, v := range volumes { 204 b, err := generateKubeYAML(v.GenerateForKube()) 205 if err != nil { 206 return nil, err 207 } 208 pvs = append(pvs, b) 209 } 210 211 return pvs, nil 212 } 213 214 // generateKubeYAML marshalls a kube kind into a YAML file. 215 func generateKubeYAML(kubeKind interface{}) ([]byte, error) { 216 b, err := yaml.Marshal(kubeKind) 217 if err != nil { 218 return nil, err 219 } 220 221 return b, nil 222 } 223 224 // generateKubeOutput generates kube YAML file containing multiple kube kinds. 225 func generateKubeOutput(content [][]byte) ([]byte, error) { 226 output := make([]byte, 0) 227 228 header := `# Save the output of this file and use kubectl create -f to import 229 # it into Kubernetes. 230 # 231 # Created with podman-%s 232 ` 233 podmanVersion, err := define.GetVersion() 234 if err != nil { 235 return nil, err 236 } 237 238 // Add header to kube YAML file. 239 output = append(output, []byte(fmt.Sprintf(header, podmanVersion.Version))...) 240 241 // kube generate order is based on helm install order (secret, persistentVolume, service, pod...). 242 // Add kube kinds. 243 for i, b := range content { 244 if i != 0 { 245 output = append(output, []byte("---\n")...) 246 } 247 248 output = append(output, b...) 249 } 250 251 return output, nil 252 }