mirror of https://github.com/kubernetes/kops.git
Create nodetasks.IssueCert()
This commit is contained in:
parent
367177f272
commit
8b9145f6c4
|
@ -18,13 +18,10 @@ package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"k8s.io/kops/pkg/pki"
|
|
||||||
"k8s.io/kops/upup/pkg/fi"
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
|
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EtcdManagerTLSBuilder configures TLS support for etcd-manager
|
// EtcdManagerTLSBuilder configures TLS support for etcd-manager
|
||||||
|
@ -69,48 +66,24 @@ func (b *EtcdManagerTLSBuilder) Build(ctx *fi.ModelBuilderContext) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We also dynamically generate the client keypair for apiserver
|
// We also dynamically generate the client keypair for apiserver
|
||||||
if err := b.buildKubeAPIServerKeypair(); err != nil {
|
if err := b.buildKubeAPIServerKeypair(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EtcdManagerTLSBuilder) buildKubeAPIServerKeypair() error {
|
func (b *EtcdManagerTLSBuilder) buildKubeAPIServerKeypair(c *fi.ModelBuilderContext) error {
|
||||||
req := &pki.IssueCertRequest{
|
name := "etcd-client"
|
||||||
|
issueCert := &nodetasks.IssueCert{
|
||||||
|
Name: name,
|
||||||
Signer: "etcd-clients-ca",
|
Signer: "etcd-clients-ca",
|
||||||
Type: "client",
|
Type: "client",
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: "kube-apiserver",
|
CommonName: "kube-apiserver",
|
||||||
},
|
},
|
||||||
MinValidDays: 455,
|
|
||||||
}
|
|
||||||
dir := "/etc/kubernetes/pki/kube-apiserver"
|
|
||||||
name := "etcd-client"
|
|
||||||
humanName := dir + "/" + name
|
|
||||||
klog.Infof("signing certificate for %q", humanName)
|
|
||||||
cert, privateKey, etcdClientsCACertificate, err := pki.IssueCert(req, b.KeyStore)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error signing certificate for %q: %v", humanName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
||||||
return fmt.Errorf("error creating directories %q: %v", dir, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
p := filepath.Join(dir, "etcd-ca.crt")
|
|
||||||
if err := etcdClientsCACertificate.WriteToFile(p, 0644); err != nil {
|
|
||||||
return fmt.Errorf("error writing certificate key file %q: %v", p, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p := filepath.Join(dir, name)
|
|
||||||
if err := cert.WriteToFile(p+".crt", 0644); err != nil {
|
|
||||||
return fmt.Errorf("error writing certificate key file %q: %v", p+".crt", err)
|
|
||||||
}
|
|
||||||
if err := privateKey.WriteToFile(p+".key", 0600); err != nil {
|
|
||||||
return fmt.Errorf("error writing private key file %q: %v", p+".key", err)
|
|
||||||
}
|
}
|
||||||
|
c.AddTask(issueCert)
|
||||||
|
issueCert.AddFileTasks(c, "/etc/kubernetes/pki/kube-apiserver", name, "etcd-ca", nil)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,9 @@ package model
|
||||||
import (
|
import (
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/klog"
|
|
||||||
"k8s.io/kops/pkg/apis/nodeup"
|
"k8s.io/kops/pkg/apis/nodeup"
|
||||||
"k8s.io/kops/pkg/pki"
|
|
||||||
"k8s.io/kops/pkg/wellknownusers"
|
"k8s.io/kops/pkg/wellknownusers"
|
||||||
"k8s.io/kops/upup/pkg/fi"
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
||||||
|
@ -85,63 +82,16 @@ func (b *KubeAPIServerBuilder) addHealthcheckSidecarTasks(c *fi.ModelBuilderCont
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
req := &pki.IssueCertRequest{
|
issueCert := &nodetasks.IssueCert{
|
||||||
|
Name: id,
|
||||||
Signer: fi.CertificateId_CA,
|
Signer: fi.CertificateId_CA,
|
||||||
Type: "client",
|
Type: "client",
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: id,
|
CommonName: id,
|
||||||
},
|
},
|
||||||
MinValidDays: 455,
|
|
||||||
}
|
}
|
||||||
|
c.AddTask(issueCert)
|
||||||
klog.Infof("signing certificate for %q", id)
|
issueCert.AddFileTasks(c, secretsDir, "client", "ca", s(userName))
|
||||||
clientCert, clientKey, _, err := pki.IssueCert(req, b.KeyStore)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c.AddTask(&nodetasks.File{
|
|
||||||
Path: filepath.Join(secretsDir),
|
|
||||||
Type: nodetasks.FileType_Directory,
|
|
||||||
Mode: s("0755"),
|
|
||||||
})
|
|
||||||
|
|
||||||
clientCertBytes, err := clientCert.AsBytes()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.AddTask(&nodetasks.File{
|
|
||||||
Path: filepath.Join(secretsDir, "client.crt"),
|
|
||||||
Contents: fi.NewBytesResource(clientCertBytes),
|
|
||||||
Type: nodetasks.FileType_File,
|
|
||||||
Mode: s("0644"),
|
|
||||||
Owner: s(userName),
|
|
||||||
})
|
|
||||||
|
|
||||||
clientKeyBytes, err := clientKey.AsBytes()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.AddTask(&nodetasks.File{
|
|
||||||
Path: filepath.Join(secretsDir, "client.key"),
|
|
||||||
Contents: fi.NewBytesResource(clientKeyBytes),
|
|
||||||
Type: nodetasks.FileType_File,
|
|
||||||
Mode: s("0600"),
|
|
||||||
Owner: s(userName),
|
|
||||||
})
|
|
||||||
|
|
||||||
cert, err := b.GetCert(fi.CertificateId_CA)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c.AddTask(&nodetasks.File{
|
|
||||||
Path: filepath.Join(secretsDir, "ca.crt"),
|
|
||||||
Contents: fi.NewBytesResource(cert),
|
|
||||||
Type: nodetasks.FileType_File,
|
|
||||||
Mode: s("0644"),
|
|
||||||
Owner: s(userName),
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ go_library(
|
||||||
"//nodeup/pkg/model:go_default_library",
|
"//nodeup/pkg/model:go_default_library",
|
||||||
"//pkg/apis/kops:go_default_library",
|
"//pkg/apis/kops:go_default_library",
|
||||||
"//pkg/model/components:go_default_library",
|
"//pkg/model/components:go_default_library",
|
||||||
"//pkg/pki:go_default_library",
|
|
||||||
"//pkg/systemd:go_default_library",
|
"//pkg/systemd:go_default_library",
|
||||||
"//upup/pkg/fi:go_default_library",
|
"//upup/pkg/fi:go_default_library",
|
||||||
"//upup/pkg/fi/nodeup/nodetasks:go_default_library",
|
"//upup/pkg/fi/nodeup/nodetasks:go_default_library",
|
||||||
|
|
|
@ -19,14 +19,10 @@ package networking
|
||||||
import (
|
import (
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"k8s.io/kops/nodeup/pkg/model"
|
"k8s.io/kops/nodeup/pkg/model"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"k8s.io/klog"
|
|
||||||
"k8s.io/kops/pkg/pki"
|
|
||||||
"k8s.io/kops/upup/pkg/fi"
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
|
||||||
)
|
)
|
||||||
|
@ -127,41 +123,17 @@ func (b *CiliumBuilder) buildCiliumEtcdSecrets(c *fi.ModelBuilderContext) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req := &pki.IssueCertRequest{
|
name := "etcd-client-cilium"
|
||||||
|
issueCert := &nodetasks.IssueCert{
|
||||||
|
Name: name,
|
||||||
Signer: "etcd-clients-ca-cilium",
|
Signer: "etcd-clients-ca-cilium",
|
||||||
Type: "client",
|
Type: "client",
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
CommonName: "cilium",
|
CommonName: "cilium",
|
||||||
},
|
},
|
||||||
MinValidDays: 455,
|
|
||||||
}
|
|
||||||
dir := "/etc/kubernetes/pki/cilium"
|
|
||||||
name := "etcd-client-cilium"
|
|
||||||
humanName := dir + "/" + name
|
|
||||||
klog.Infof("signing certificate for %q", humanName)
|
|
||||||
cert, privateKey, etcdClientsCACertificate, err := pki.IssueCert(req, b.KeyStore)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error signing certificate for %q: %v", humanName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
||||||
return fmt.Errorf("error creating directories %q: %v", dir, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
p := filepath.Join(dir, "etcd-ca.crt")
|
|
||||||
if err := etcdClientsCACertificate.WriteToFile(p, 0644); err != nil {
|
|
||||||
return fmt.Errorf("error writing certificate key file %q: %v", p, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p := filepath.Join(dir, name)
|
|
||||||
if err := cert.WriteToFile(p+".crt", 0644); err != nil {
|
|
||||||
return fmt.Errorf("error writing certificate key file %q: %v", p+".crt", err)
|
|
||||||
}
|
|
||||||
if err := privateKey.WriteToFile(p+".key", 0600); err != nil {
|
|
||||||
return fmt.Errorf("error writing private key file %q: %v", p+".key", err)
|
|
||||||
}
|
}
|
||||||
|
c.AddTask(issueCert)
|
||||||
|
issueCert.AddFileTasks(c, "/etc/kubernetes/pki/cilium", name, "etcd-ca", nil)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,6 +199,8 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
|
||||||
NodeupConfig: c.config,
|
NodeupConfig: c.config,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var secretStore fi.SecretStore
|
||||||
|
var keyStore fi.Keystore
|
||||||
if c.cluster.Spec.SecretStore != "" {
|
if c.cluster.Spec.SecretStore != "" {
|
||||||
klog.Infof("Building SecretStore at %q", c.cluster.Spec.SecretStore)
|
klog.Infof("Building SecretStore at %q", c.cluster.Spec.SecretStore)
|
||||||
p, err := vfs.Context.BuildVfsPath(c.cluster.Spec.SecretStore)
|
p, err := vfs.Context.BuildVfsPath(c.cluster.Spec.SecretStore)
|
||||||
|
@ -206,7 +208,8 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
|
||||||
return fmt.Errorf("error building secret store path: %v", err)
|
return fmt.Errorf("error building secret store path: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
modelContext.SecretStore = secrets.NewVFSSecretStore(c.cluster, p)
|
secretStore = secrets.NewVFSSecretStore(c.cluster, p)
|
||||||
|
modelContext.SecretStore = secretStore
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("SecretStore not set")
|
return fmt.Errorf("SecretStore not set")
|
||||||
}
|
}
|
||||||
|
@ -219,6 +222,7 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
modelContext.KeyStore = fi.NewVFSCAStore(c.cluster, p)
|
modelContext.KeyStore = fi.NewVFSCAStore(c.cluster, p)
|
||||||
|
keyStore = modelContext.KeyStore
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("KeyStore not set")
|
return fmt.Errorf("KeyStore not set")
|
||||||
}
|
}
|
||||||
|
@ -285,8 +289,6 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
|
||||||
// Protokube load image task is in ProtokubeBuilder
|
// Protokube load image task is in ProtokubeBuilder
|
||||||
|
|
||||||
var cloud fi.Cloud
|
var cloud fi.Cloud
|
||||||
var keyStore fi.Keystore
|
|
||||||
var secretStore fi.SecretStore
|
|
||||||
var target fi.Target
|
var target fi.Target
|
||||||
checkExisting := true
|
checkExisting := true
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ go_library(
|
||||||
"createsdir.go",
|
"createsdir.go",
|
||||||
"file.go",
|
"file.go",
|
||||||
"group.go",
|
"group.go",
|
||||||
|
"issue_cert.go",
|
||||||
"load_image.go",
|
"load_image.go",
|
||||||
"package.go",
|
"package.go",
|
||||||
"service.go",
|
"service.go",
|
||||||
|
@ -20,6 +21,7 @@ go_library(
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/backoff:go_default_library",
|
"//pkg/backoff:go_default_library",
|
||||||
|
"//pkg/pki:go_default_library",
|
||||||
"//upup/pkg/fi:go_default_library",
|
"//upup/pkg/fi:go_default_library",
|
||||||
"//upup/pkg/fi/nodeup/cloudinit:go_default_library",
|
"//upup/pkg/fi/nodeup/cloudinit:go_default_library",
|
||||||
"//upup/pkg/fi/nodeup/local:go_default_library",
|
"//upup/pkg/fi/nodeup/local:go_default_library",
|
||||||
|
@ -37,9 +39,13 @@ go_test(
|
||||||
"archive_test.go",
|
"archive_test.go",
|
||||||
"bindmount_test.go",
|
"bindmount_test.go",
|
||||||
"file_test.go",
|
"file_test.go",
|
||||||
|
"issue_cert_test.go",
|
||||||
"loadimage_test.go",
|
"loadimage_test.go",
|
||||||
"service_test.go",
|
"service_test.go",
|
||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = ["//upup/pkg/fi:go_default_library"],
|
deps = [
|
||||||
|
"//upup/pkg/fi:go_default_library",
|
||||||
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -98,6 +98,10 @@ func (e *File) GetDependencies(tasks map[string]fi.Task) []fi.Task {
|
||||||
// Requires parent directories to be created
|
// Requires parent directories to be created
|
||||||
deps = append(deps, findCreatesDirParents(e.Path, tasks)...)
|
deps = append(deps, findCreatesDirParents(e.Path, tasks)...)
|
||||||
|
|
||||||
|
if hasDep, ok := e.Contents.(fi.HasDependencies); ok {
|
||||||
|
deps = append(deps, hasDep.GetDependencies(tasks)...)
|
||||||
|
}
|
||||||
|
|
||||||
// Requires other files to be created first
|
// Requires other files to be created first
|
||||||
for _, f := range e.AfterFiles {
|
for _, f := range e.AfterFiles {
|
||||||
for _, v := range tasks {
|
for _, v := range tasks {
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nodetasks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"k8s.io/klog"
|
||||||
|
"k8s.io/kops/pkg/pki"
|
||||||
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IssueCert struct {
|
||||||
|
Name string
|
||||||
|
|
||||||
|
Signer string `json:"signer"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Subject pkix.Name `json:"subject"`
|
||||||
|
AlternateNames []string `json:"alternateNames,omitempty"`
|
||||||
|
|
||||||
|
cert *fi.TaskDependentResource
|
||||||
|
key *fi.TaskDependentResource
|
||||||
|
ca *fi.TaskDependentResource
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ fi.Task = &IssueCert{}
|
||||||
|
var _ fi.HasName = &IssueCert{}
|
||||||
|
|
||||||
|
func (i *IssueCert) GetName() *string {
|
||||||
|
return &i.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IssueCert) SetName(name string) {
|
||||||
|
i.Name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation, implementing the Stringer interface
|
||||||
|
func (i *IssueCert) String() string {
|
||||||
|
return fmt.Sprintf("IssueCert: %s", i.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IssueCert) GetResources() (certResource, keyResource, caResource *fi.TaskDependentResource) {
|
||||||
|
if i.cert == nil {
|
||||||
|
i.cert = &fi.TaskDependentResource{Task: i}
|
||||||
|
i.key = &fi.TaskDependentResource{Task: i}
|
||||||
|
i.ca = &fi.TaskDependentResource{Task: i}
|
||||||
|
}
|
||||||
|
return i.cert, i.key, i.ca
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IssueCert) AddFileTasks(c *fi.ModelBuilderContext, dir string, name string, caName string, owner *string) {
|
||||||
|
certResource, keyResource, caResource := i.GetResources()
|
||||||
|
c.AddTask(&File{
|
||||||
|
Path: dir,
|
||||||
|
Type: FileType_Directory,
|
||||||
|
Mode: fi.String("0755"),
|
||||||
|
})
|
||||||
|
|
||||||
|
c.AddTask(&File{
|
||||||
|
Path: filepath.Join(dir, name+".crt"),
|
||||||
|
Contents: certResource,
|
||||||
|
Type: FileType_File,
|
||||||
|
Mode: fi.String("0644"),
|
||||||
|
Owner: owner,
|
||||||
|
})
|
||||||
|
|
||||||
|
c.AddTask(&File{
|
||||||
|
Path: filepath.Join(dir, name+".key"),
|
||||||
|
Contents: keyResource,
|
||||||
|
Type: FileType_File,
|
||||||
|
Mode: fi.String("0600"),
|
||||||
|
Owner: owner,
|
||||||
|
})
|
||||||
|
|
||||||
|
if caName != "" {
|
||||||
|
c.AddTask(&File{
|
||||||
|
Path: filepath.Join(dir, caName+".crt"),
|
||||||
|
Contents: caResource,
|
||||||
|
Type: FileType_File,
|
||||||
|
Mode: fi.String("0644"),
|
||||||
|
Owner: owner,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *IssueCert) Run(c *fi.Context) error {
|
||||||
|
req := &pki.IssueCertRequest{
|
||||||
|
Signer: e.Signer,
|
||||||
|
Type: e.Type,
|
||||||
|
Subject: e.Subject,
|
||||||
|
MinValidDays: 455,
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.Infof("signing certificate for %q", e.Name)
|
||||||
|
certificate, privateKey, caCertificate, err := pki.IssueCert(req, c.Keystore)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
certResource, keyResource, caResource := e.GetResources()
|
||||||
|
certResource.Resource = &asBytesResource{certificate}
|
||||||
|
keyResource.Resource = &asBytesResource{privateKey}
|
||||||
|
caResource.Resource = &asBytesResource{caCertificate}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type hasAsBytes interface {
|
||||||
|
AsBytes() ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type asBytesResource struct {
|
||||||
|
hasAsBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a asBytesResource) Open() (io.Reader, error) {
|
||||||
|
data, err := a.AsBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bytes.NewReader(data), nil
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nodetasks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"k8s.io/kops/upup/pkg/fi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIssueCertFileDependencies(t *testing.T) {
|
||||||
|
context := &fi.ModelBuilderContext{
|
||||||
|
Tasks: make(map[string]fi.Task),
|
||||||
|
}
|
||||||
|
|
||||||
|
issue := &IssueCert{Name: "testCert"}
|
||||||
|
context.AddTask(issue)
|
||||||
|
issue.AddFileTasks(context, "/tmp", "testCert", "testCa", nil)
|
||||||
|
var taskNames []string
|
||||||
|
for name := range context.Tasks {
|
||||||
|
taskNames = append(taskNames, name)
|
||||||
|
}
|
||||||
|
assert.ElementsMatch(t, []string{"IssueCert/testCert", "File//tmp", "File//tmp/testCert.crt", "File//tmp/testCert.key", "File//tmp/testCa.crt"}, taskNames)
|
||||||
|
|
||||||
|
for _, fileName := range []string{"/tmp/testCert.crt", "/tmp/testCert.key", "/tmp/testCa.crt"} {
|
||||||
|
task := context.Tasks["File/"+fileName]
|
||||||
|
if !assert.NotNil(t, task) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
deps := task.(fi.HasDependencies).GetDependencies(context.Tasks)
|
||||||
|
|
||||||
|
taskNames = nil
|
||||||
|
for _, task := range deps {
|
||||||
|
taskNames = append(taskNames, *task.(fi.HasName).GetName())
|
||||||
|
}
|
||||||
|
assert.ElementsMatch(t, []string{"testCert", "/tmp"}, taskNames)
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,13 +64,13 @@ func (p *Service) GetDependencies(tasks map[string]fi.Task) []fi.Task {
|
||||||
var deps []fi.Task
|
var deps []fi.Task
|
||||||
for _, v := range tasks {
|
for _, v := range tasks {
|
||||||
// We assume that services depend on everything except for
|
// We assume that services depend on everything except for
|
||||||
// LoadImageTask. If there are any LoadImageTasks (e.g. we're
|
// LoadImageTask or IssueCert. If there are any LoadImageTasks (e.g. we're
|
||||||
// launching a custom Kubernetes build), they all depend on
|
// launching a custom Kubernetes build), they all depend on
|
||||||
// the "docker.service" Service task.
|
// the "docker.service" Service task.
|
||||||
switch v.(type) {
|
switch v.(type) {
|
||||||
case *File, *Package, *UpdatePackages, *UserTask, *GroupTask, *Chattr, *BindMount, *Archive:
|
case *File, *Package, *UpdatePackages, *UserTask, *GroupTask, *Chattr, *BindMount, *Archive:
|
||||||
deps = append(deps, v)
|
deps = append(deps, v)
|
||||||
case *Service, *LoadImageTask:
|
case *Service, *LoadImageTask, *IssueCert:
|
||||||
// ignore
|
// ignore
|
||||||
default:
|
default:
|
||||||
klog.Warningf("Unhandled type %T in Service::GetDependencies: %v", v, v)
|
klog.Warningf("Unhandled type %T in Service::GetDependencies: %v", v, v)
|
||||||
|
|
|
@ -248,3 +248,22 @@ func WrapResource(r Resource) *ResourceHolder {
|
||||||
Resource: r,
|
Resource: r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TaskDependentResource struct {
|
||||||
|
Resource Resource
|
||||||
|
Task Task
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Resource = &TaskDependentResource{}
|
||||||
|
var _ HasDependencies = &TaskDependentResource{}
|
||||||
|
|
||||||
|
func (r *TaskDependentResource) Open() (io.Reader, error) {
|
||||||
|
if r.Resource == nil {
|
||||||
|
return nil, fmt.Errorf("resource opened before it is ready")
|
||||||
|
}
|
||||||
|
return r.Resource.Open()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *TaskDependentResource) GetDependencies(tasks map[string]Task) []Task {
|
||||||
|
return []Task{r.Task}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue