Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pull secrets and re-write image in Pod objects #888

Merged
merged 1 commit into from
Jul 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/base/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type FindPrivateImagesOptions struct {

type FindPrivateImagesResult struct {
Images []kustomizeimage.Image // images to be rewritten
Docs []*k8sdoc.Doc // docs that have rewritten images
Docs []k8sdoc.K8sDoc // docs that have rewritten images
CheckedImages []kotsv1beta1.InstallationImage // all images found in the installation
}

Expand Down Expand Up @@ -66,7 +66,7 @@ type FindObjectsWithImagesOptions struct {
BaseDir string
}

func FindObjectsWithImages(options FindObjectsWithImagesOptions) ([]*k8sdoc.Doc, error) {
func FindObjectsWithImages(options FindObjectsWithImagesOptions) ([]k8sdoc.K8sDoc, error) {
objects, err := image.GetObjectsWithImages(options.BaseDir)
if err != nil {
return nil, errors.Wrap(err, "failed to list upstream images")
Expand Down
38 changes: 11 additions & 27 deletions pkg/image/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/replicatedhq/kots/pkg/docker/registry"
"github.com/replicatedhq/kots/pkg/k8sdoc"
"github.com/replicatedhq/kots/pkg/logger"
"gopkg.in/yaml.v2"
kustomizeimage "sigs.k8s.io/kustomize/api/types"
)

Expand Down Expand Up @@ -90,10 +89,10 @@ func CopyImages(srcRegistry, destRegistry registry.RegistryOptions, appSlug stri
return newImages, nil
}

func GetPrivateImages(upstreamDir string, checkedImages map[string]ImageInfo, allPrivate bool) ([]string, []*k8sdoc.Doc, error) {
func GetPrivateImages(upstreamDir string, checkedImages map[string]ImageInfo, allPrivate bool) ([]string, []k8sdoc.K8sDoc, error) {
uniqueImages := make(map[string]bool)

objects := make([]*k8sdoc.Doc, 0) // all objects where images are referenced from
objects := make([]k8sdoc.K8sDoc, 0) // all objects where images are referenced from

err := filepath.Walk(upstreamDir,
func(path string, info os.FileInfo, err error) error {
Expand All @@ -110,7 +109,7 @@ func GetPrivateImages(upstreamDir string, checkedImages map[string]ImageInfo, al
return err
}

return listImagesInFile(contents, func(images []string, doc *k8sdoc.Doc) error {
return listImagesInFile(contents, func(images []string, doc k8sdoc.K8sDoc) error {
numPrivateImages := 0
for _, image := range images {
if allPrivate {
Expand Down Expand Up @@ -164,8 +163,8 @@ func GetPrivateImages(upstreamDir string, checkedImages map[string]ImageInfo, al
return result, objects, nil
}

func GetObjectsWithImages(upstreamDir string) ([]*k8sdoc.Doc, error) {
objects := make([]*k8sdoc.Doc, 0)
func GetObjectsWithImages(upstreamDir string) ([]k8sdoc.K8sDoc, error) {
objects := make([]k8sdoc.K8sDoc, 0)

err := filepath.Walk(upstreamDir,
func(path string, info os.FileInfo, err error) error {
Expand All @@ -182,7 +181,7 @@ func GetObjectsWithImages(upstreamDir string) ([]*k8sdoc.Doc, error) {
return err
}

return listImagesInFile(contents, func(images []string, doc *k8sdoc.Doc) error {
return listImagesInFile(contents, func(images []string, doc k8sdoc.K8sDoc) error {
if len(images) > 0 {
objects = append(objects, doc)
}
Expand Down Expand Up @@ -215,7 +214,7 @@ func copyImagesInFileBetweenRegistries(srcRegistry, destRegistry registry.Regist
savedImages[fmt.Sprintf("%s:%s", image.Name, image.NewTag)] = true
}

err := listImagesInFile(fileData, func(images []string, doc *k8sdoc.Doc) error {
err := listImagesInFile(fileData, func(images []string, doc k8sdoc.K8sDoc) error {
for _, image := range images {
if _, saved := savedImages[image]; saved {
continue
Expand All @@ -242,32 +241,17 @@ func copyImagesInFileBetweenRegistries(srcRegistry, destRegistry registry.Regist
return newImages, err
}

type processImagesFunc func([]string, *k8sdoc.Doc) error
type processImagesFunc func([]string, k8sdoc.K8sDoc) error

func listImagesInFile(contents []byte, handler processImagesFunc) error {
yamlDocs := bytes.Split(contents, []byte("\n---\n"))
for _, yamlDoc := range yamlDocs {
parsed := &k8sdoc.Doc{}
if err := yaml.Unmarshal(yamlDoc, parsed); err != nil {
parsed, err := k8sdoc.ParseYAML(yamlDoc)
if err != nil {
continue
}

images := make([]string, 0)
for _, container := range parsed.Spec.Template.Spec.Containers {
images = append(images, container.Image)
}

for _, container := range parsed.Spec.Template.Spec.InitContainers {
images = append(images, container.Image)
}

for _, container := range parsed.Spec.JobTemplate.Spec.Template.Spec.InitContainers {
images = append(images, container.Image)
}

for _, container := range parsed.Spec.JobTemplate.Spec.Template.Spec.Containers {
images = append(images, container.Image)
}
images := parsed.ListImages()

if err := handler(images, parsed); err != nil {
return err
Expand Down
125 changes: 125 additions & 0 deletions pkg/k8sdoc/types.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
package k8sdoc

import (
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
corev1 "k8s.io/api/core/v1"
)

type K8sDoc interface {
PatchWithPullSecret(secret *corev1.Secret) K8sDoc
ListImages() []string
}

type Doc struct {
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata Metadata `yaml:"metadata"`
Spec Spec `yaml:"spec"`
}

type PodDoc struct {
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata Metadata `yaml:"metadata"`
Spec PodSpec `yaml:"spec"`
}

type Metadata struct {
Name string `yaml:"name"`
Namespace string `yaml:"namespace,omitempty"`
Expand Down Expand Up @@ -41,3 +59,110 @@ type ImagePullSecret map[string]string
type Container struct {
Image string `yaml:"image"`
}

func ParseYAML(yamlDoc []byte) (K8sDoc, error) {
doc := &Doc{}
if err := yaml.Unmarshal(yamlDoc, doc); err != nil {
return nil, errors.Wrap(err, "failed to parse yaml")
}

if doc.Kind != "Pod" {
return doc, nil
}

podDoc := &PodDoc{}
if err := yaml.Unmarshal(yamlDoc, podDoc); err != nil {
return nil, errors.Wrap(err, "failed to parse yaml")
}
return podDoc, nil
}

func (d *Doc) PatchWithPullSecret(secret *corev1.Secret) K8sDoc {
newObj := &Doc{
APIVersion: d.APIVersion,
Kind: d.Kind,
Metadata: Metadata{
Name: d.Metadata.Name,
Namespace: d.Metadata.Namespace,
Labels: d.Metadata.Labels,
},
}
switch d.Kind {
case "CronJob":
newObj.Spec = Spec{
JobTemplate: JobTemplate{
Spec: JobSpec{
Template: Template{
Spec: PodSpec{
ImagePullSecrets: []ImagePullSecret{
{"name": "kotsadm-replicated-registry"},
},
},
},
},
},
}

default:
newObj.Spec = Spec{
Template: Template{
Spec: PodSpec{
ImagePullSecrets: []ImagePullSecret{
{"name": "kotsadm-replicated-registry"},
},
},
},
}
}

return newObj
}

func (d *Doc) ListImages() []string {
images := make([]string, 0)
for _, container := range d.Spec.Template.Spec.Containers {
images = append(images, container.Image)
}

for _, container := range d.Spec.Template.Spec.InitContainers {
images = append(images, container.Image)
}

for _, container := range d.Spec.JobTemplate.Spec.Template.Spec.InitContainers {
images = append(images, container.Image)
}

for _, container := range d.Spec.JobTemplate.Spec.Template.Spec.Containers {
images = append(images, container.Image)
}
return images
}

func (d *PodDoc) PatchWithPullSecret(secret *corev1.Secret) K8sDoc {
return &PodDoc{
APIVersion: d.APIVersion,
Kind: d.Kind,
Metadata: Metadata{
Name: d.Metadata.Name,
Namespace: d.Metadata.Namespace,
Labels: d.Metadata.Labels,
},
Spec: PodSpec{
ImagePullSecrets: []ImagePullSecret{
{"name": "kotsadm-replicated-registry"},
},
},
}
}

func (d *PodDoc) ListImages() []string {
images := make([]string, 0)
for _, container := range d.Spec.Containers {
images = append(images, container.Image)
}

for _, container := range d.Spec.InitContainers {
images = append(images, container.Image)
}
return images
}
4 changes: 2 additions & 2 deletions pkg/midstream/midstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import (
type Midstream struct {
Kustomization *kustomizetypes.Kustomization
Base *base.Base
DocForPatches []*k8sdoc.Doc
DocForPatches []k8sdoc.K8sDoc
PullSecret *corev1.Secret
}

func CreateMidstream(b *base.Base, images []kustomizetypes.Image, objects []*k8sdoc.Doc, pullSecret *corev1.Secret) (*Midstream, error) {
func CreateMidstream(b *base.Base, images []kustomizetypes.Image, objects []k8sdoc.K8sDoc, pullSecret *corev1.Secret) (*Midstream, error) {
kustomization := kustomizetypes.Kustomization{
TypeMeta: kustomizetypes.TypeMeta{
APIVersion: "kustomize.config.k8s.io/v1beta1",
Expand Down
45 changes: 1 addition & 44 deletions pkg/midstream/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import (
"path/filepath"

"github.com/pkg/errors"
"github.com/replicatedhq/kots/pkg/k8sdoc"
"github.com/replicatedhq/kots/pkg/k8sutil"
yaml "gopkg.in/yaml.v2"
corev1 "k8s.io/api/core/v1"
kustomizetypes "sigs.k8s.io/kustomize/api/types"
k8syaml "sigs.k8s.io/yaml"
)
Expand Down Expand Up @@ -161,7 +159,7 @@ func (m *Midstream) writeObjectsWithPullSecret(options WriteOptions) error {
defer f.Close()

for _, o := range m.DocForPatches {
withPullSecret := obejctWithPullSecret(o, m.PullSecret)
withPullSecret := o.PatchWithPullSecret(m.PullSecret)

b, err := yaml.Marshal(withPullSecret)
if err != nil {
Expand Down Expand Up @@ -190,44 +188,3 @@ func removeFromPatches(patches []kustomizetypes.PatchStrategicMerge, filename st
}
return newPatches
}

func obejctWithPullSecret(obj *k8sdoc.Doc, secret *corev1.Secret) *k8sdoc.Doc {
newObj := &k8sdoc.Doc{
APIVersion: obj.APIVersion,
Kind: obj.Kind,
Metadata: k8sdoc.Metadata{
Name: obj.Metadata.Name,
Namespace: obj.Metadata.Namespace,
Labels: obj.Metadata.Labels,
},
}
switch obj.Kind {
case "CronJob":
newObj.Spec = k8sdoc.Spec{
JobTemplate: k8sdoc.JobTemplate{
Spec: k8sdoc.JobSpec{
Template: k8sdoc.Template{
Spec: k8sdoc.PodSpec{
ImagePullSecrets: []k8sdoc.ImagePullSecret{
{"name": "kotsadm-replicated-registry"},
},
},
},
},
},
}

default:
newObj.Spec = k8sdoc.Spec{
Template: k8sdoc.Template{
Spec: k8sdoc.PodSpec{
ImagePullSecrets: []k8sdoc.ImagePullSecret{
{"name": "kotsadm-replicated-registry"},
},
},
},
}
}

return newObj
}
2 changes: 1 addition & 1 deletion pkg/pull/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) {

var pullSecret *corev1.Secret
var images []kustomizetypes.Image
var objects []*k8sdoc.Doc
var objects []k8sdoc.K8sDoc
if pullOptions.RewriteImages {

log.ActionWithSpinner("Copying private images")
Expand Down
2 changes: 1 addition & 1 deletion pkg/rewrite/rewrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func Rewrite(rewriteOptions RewriteOptions) error {

var pullSecret *corev1.Secret
var images []kustomizetypes.Image
var objects []*k8sdoc.Doc
var objects []k8sdoc.K8sDoc

if rewriteOptions.CopyImages || rewriteOptions.RegistryEndpoint != "" {
// When CopyImages is set, we copy images, rewrite all images, and use registry
Expand Down