Skip to content
This repository was archived by the owner on Feb 5, 2020. It is now read-only.
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.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 18 additions & 0 deletions config.tf
Original file line number Diff line number Diff line change
Expand Up @@ -518,3 +518,21 @@ It is only supported for Azure cloud provider.
Used to collect the boot logs for debug purposes.
EOF
}

variable "tectonic_ignition_master" {
type = "string"
default = ""

description = <<EOF
(internal) Ignition config file path. This is automatically generated by the installer.
EOF
}

variable "tectonic_ignition_worker" {
type = "string"
default = ""

description = <<EOF
(internal) Ignition config file path. This is automatically generated by the installer.
EOF
}
45 changes: 36 additions & 9 deletions installer/glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions installer/glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ import:
version: kubernetes-1.9.0
- package: golang.org/x/crypto
version: 5dc8cb4b8a8eb076cbb5a06bc3b8682c15bdbbd3
- package: github.com/coreos/ignition
version: v0.23.0
3 changes: 3 additions & 0 deletions installer/pkg/config-generator/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ go_library(
name = "go_default_library",
srcs = [
"generator.go",
"ignition.go",
],
importpath = "github.com/coreos/tectonic-installer/installer/pkg/config-generator",
visibility = ["//visibility:public"],
deps = [
"//installer/pkg/config:go_default_library",
"//installer/vendor/github.com/apparentlymart/go-cidr/cidr:go_default_library",
"//installer/vendor/github.com/coreos/ignition/config/v2_0:go_default_library",
"//installer/vendor/github.com/coreos/ignition/config/v2_0/types:go_default_library",
"//installer/vendor/github.com/coreos/tectonic-config/config/kube-addon:go_default_library",
"//installer/vendor/github.com/coreos/tectonic-config/config/kube-core:go_default_library",
"//installer/vendor/github.com/coreos/tectonic-config/config/tectonic-network:go_default_library",
Expand Down
160 changes: 160 additions & 0 deletions installer/pkg/config-generator/ignition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package configgenerator

import (
"bufio"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"

ignconfig "github.com/coreos/ignition/config/v2_0"
ignconfigtypes "github.com/coreos/ignition/config/v2_0/types"
"github.com/coreos/tectonic-installer/installer/pkg/config"
)

var (
ignVersion = ignconfigtypes.IgnitionVersion{2, 0, 0, "", ""}
ignFilesPath = map[string]string{
"master": config.IgnitionMaster,
"worker": config.IgnitionWorker,
"etcd": config.IgnitionEtcd,
}
)

const (
kubeconfigKubeletPath = "generated/auth/kubeconfig-kubelet"
)

func (c ConfigGenerator) poolToRoleMap() map[string]string {
poolToRole := make(map[string]string)
// assume no roles can share pools
for _, n := range c.Master.NodePools {
poolToRole[n] = "master"
}
for _, n := range c.Worker.NodePools {
poolToRole[n] = "worker"
}
for _, n := range c.Etcd.NodePools {
poolToRole[n] = "etcd"
}
return poolToRole
}

// GenerateIgnConfig generates, if successful, files with the ign config for each role.
func (c ConfigGenerator) GenerateIgnConfig(clusterDir string) error {
poolToRole := c.poolToRoleMap()
for _, p := range c.NodePools {
ignFile := p.IgnitionFile
ignCfg, err := parseIgnFile(ignFile)
if err != nil {
return fmt.Errorf("failed to GenerateIgnConfig for pool %s and file %s: %v", p.Name, p.IgnitionFile, err)
}
role := poolToRole[p.Name]
// TODO(alberto): Append block need to be different for each etcd node.
// add loop over count if role is etcd
c.embedAppendBlock(ignCfg, role)
if role != "etcd" {
kubeconfigKubeletContent, err := getKubeconfigKubeletContent(clusterDir)
if err != nil {
return err
}
c.embedKubeconfigKubeletBlock(ignCfg, kubeconfigKubeletContent)
}

fileTargetPath := filepath.Join(clusterDir, ignFilesPath[role])
if err = ignCfgToFile(*ignCfg, fileTargetPath); err != nil {
return err
}
}
return nil
}

func parseIgnFile(filePath string) (*ignconfigtypes.Config, error) {
if filePath == "" {
ignition := &ignconfigtypes.Ignition{
Version: ignVersion,
}
return &ignconfigtypes.Config{Ignition: *ignition}, nil
}

data, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, err
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error seems to be completely ignored

cfg, rpt, _ := ignconfig.Parse(data)
if len(rpt.Entries) > 0 {
return nil, fmt.Errorf("failed to parse ignition file %s: %s", filePath, rpt.String())
}

return &cfg, nil
}

func (c ConfigGenerator) embedAppendBlock(ignCfg *ignconfigtypes.Config, role string) *ignconfigtypes.Config {
appendBlock := ignconfigtypes.ConfigReference{
c.getTNCURL(role),
ignconfigtypes.Verification{Hash: nil},
}
ignCfg.Ignition.Config.Append = append(ignCfg.Ignition.Config.Append, appendBlock)
return ignCfg
}

func getKubeconfigKubeletContent(clusterDir string) ([]byte, error) {
kubeconfigKubeletPath := filepath.Join(clusterDir, kubeconfigKubeletPath)
return ioutil.ReadFile(kubeconfigKubeletPath)
}

func (c ConfigGenerator) embedKubeconfigKubeletBlock(ignCfg *ignconfigtypes.Config, kubeconfiKubeletContent []byte) *ignconfigtypes.Config {
kubeconfigKubelet := ignconfigtypes.File{
Path: "/etc/kubernetes/kubeconfig",
Mode: 420,
Filesystem: "root",
Contents: ignconfigtypes.FileContents{
Source: ignconfigtypes.Url{
Scheme: "data",
Opaque: fmt.Sprintf("text/plain;charset=utf-8;base64,%s", base64.StdEncoding.EncodeToString(kubeconfiKubeletContent)),
},
},
}
ignCfg.Storage.Files = append(ignCfg.Storage.Files, kubeconfigKubelet)
return ignCfg
}

func (c ConfigGenerator) getTNCURL(role string) ignconfigtypes.Url {
var url ignconfigtypes.Url
if role == "master" || role == "worker" {
url = ignconfigtypes.Url{
Scheme: "http",
Host: fmt.Sprintf("%s-tnc.%s", c.Name, c.BaseDomain),
Path: fmt.Sprintf("/ign/v1/role/%s", role),
}
}
return url
}

func ignCfgToFile(ignCfg ignconfigtypes.Config, filePath string) error {
data, err := json.MarshalIndent(&ignCfg, "", " ")
if err != nil {
return err
}

return writeFile(filePath, string(data))
}

func writeFile(path, content string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()

w := bufio.NewWriter(f)
if _, err := fmt.Fprintln(w, content); err != nil {
return err
}
w.Flush()

return nil
}
2 changes: 2 additions & 0 deletions installer/pkg/config/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_test(
name = "go_default_test",
srcs = ["validate_test.go"],
data = glob(["fixtures/**"]),
embed = [":go_default_library"],
)

Expand All @@ -24,6 +25,7 @@ go_library(
"//installer/pkg/config/metal:go_default_library",
"//installer/pkg/config/openstack:go_default_library",
"//installer/pkg/config/vmware:go_default_library",
"//installer/vendor/github.com/coreos/ignition/config/v2_0:go_default_library",
"//installer/vendor/gopkg.in/yaml.v2:go_default_library",
],
)
15 changes: 15 additions & 0 deletions installer/pkg/config/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ import (
"github.com/coreos/tectonic-installer/installer/pkg/config/vmware"
)

const (
// IgnitionMaster is the relative path to the ign master cfg from the tf working directory
IgnitionMaster = "ignition-master.ign"
// IgnitionWorker is the relative path to the ign worker cfg from the tf working directory
IgnitionWorker = "ignition-worker.ign"
// IgnitionEtcd is the relative path to the ign etcd cfg from the tf working directory
IgnitionEtcd = "ignition-etcd.ign"
)

// Cluster defines the config for a cluster.
type Cluster struct {
Admin `json:",inline" yaml:"admin,omitempty"`
Expand Down Expand Up @@ -43,6 +52,9 @@ type Cluster struct {
metal.Metal `json:",inline" yaml:"metal,omitempty"`
openstack.OpenStack `json:",inline" yaml:"openstack,omitempty"`
vmware.VMware `json:",inline" yaml:"vmware,omitempty"`
IgnitionMaster string `json:"tectonic_ignition_master,omitempty" yaml:"-"`
IgnitionWorker string `json:"tectonic_ignition_worker,omitempty" yaml:"-"`
IgnitionEtcd string `json:"tectonic_ignition_etcd,omitempty" yaml:"-"`
}

// NodeCount will return the number of nodes specified in NodePools with matching names.
Expand All @@ -66,6 +78,9 @@ func (c *Cluster) TFVars() (string, error) {
c.Master.Count = c.NodeCount(c.Master.NodePools)
c.Worker.Count = c.NodeCount(c.Worker.NodePools)

c.IgnitionMaster = IgnitionMaster
c.IgnitionWorker = IgnitionWorker
c.IgnitionEtcd = IgnitionEtcd
data, err := json.MarshalIndent(&c, "", " ")
if err != nil {
return "", err
Expand Down
9 changes: 9 additions & 0 deletions installer/pkg/config/fixtures/ign.ign
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"ignition": { "version": "2.0.0" },
"systemd": {
"units": [{
"name": "example.service",
"contents": "[Service]\nType=oneshot\nExecStart=/usr/bin/echo Hello World\n\n[Install]\nWantedBy=multi-user.target"
}]
}
}
10 changes: 10 additions & 0 deletions installer/pkg/config/fixtures/invalid-ign.ign
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"ignition": { "version": "2.0.0" },
"systemd": {
"units": [{
"name": "example.service",
"contents": "[Service]\nType=oneshot\nExecStart=/usr/bin/echo Hello World\n\n[Install]\nWantedBy=multi-user.target"
}]
}
"invalid": ""
}
5 changes: 3 additions & 2 deletions installer/pkg/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ type ISCSI struct {

// NodePool converts node pool related config.
type NodePool struct {
Count int `json:"-" yaml:"count"`
Name string `json:"-" yaml:"name"`
Count int `json:"-" yaml:"count"`
Name string `json:"-" yaml:"name"`
IgnitionFile string `json:"-" yaml:"ignitionFile"`
}

// NodePools converts node pools related config.
Expand Down
Loading