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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Dockerfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ FROM ARG_FROM
MAINTAINER CoreOS Inc. <coreos-dev@googlegroups.com>

ADD bin/docker-rootfs-ARG_ARCH.tgz /
ADD versions.yaml /versions.yaml
ADD app-signing-pubkey.gpg /pubring.gpg
6 changes: 2 additions & 4 deletions Documentation/bootstrapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@ The bootstrapper tries to gather state from the cluster and from a [remote bucke
This is the logic flow and the information sources it queries:
1. Get cluster version from api-server `/version` endpoint
1. Iff previous step permanently failed, use `/etc/kubernetes/installer/kubelet.env` to determine the install-time kubernetes version.
1. Get needed addon (docker) versions from `/versions.yaml` hardcoded inside tectonic-torcx container
* FUTURE - after getting rid of in-container runtime mappings instead:
* Get runtime mappings from `tectonic-torcx-runtime-mappings` ConfigMap
* Iff previous step permanently failed, use `/etc/kubernetes/installer/runtime-mappings.yaml` to determine runtime mappings
1. Get runtime mappings from `tectonic-torcx-runtime-mappings` ConfigMap
1. Iff previous step permanently failed, use `/etc/kubernetes/installer/runtime-mappings.yaml` to determine runtime mappings
1. Retrieve current OS version from `/usr/lib/os-release`
1. Gather next OS version (if any) from `update_engine` via DBus
1. Retrieve torcx remote manifests for both OS versions from a remote URL (see configuration notes above)
Expand Down
16 changes: 0 additions & 16 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ VERSION ?= $(shell git describe --tags --always --dirty)
# Multicall binaries (symlink basenames).
MULTICALLS := tectonic-torcx-bootstrap tectonic-torcx-hook-pre

# The installer uses a mutable tag; tag all production
# builds with that
PRODTAG := installer-latest

###
### These variables should not need tweaking.
###
Expand Down Expand Up @@ -126,20 +122,8 @@ endif
@docker images -q $(IMAGE):$(VERSION) > $@


push-production:
@git describe --tags --exact-match > /dev/null # This will error if this is not a tagged commit
ifneq (,$(findstring dirty,$(VERSION)))
@echo "working tree is dirty, quitting"
@exit 1
endif

@docker tag $(IMAGE):$(VERSION) $(IMAGE):$(PRODTAG)
@docker push $(IMAGE):$(PRODTAG)
@echo "pushed: $(IMAGE):$(PRODTAG)"

push-name:
@echo "pushed: $(IMAGE):$(VERSION)"
@echo "You probably want to update the installer's tag with make push-production"

version:
@echo $(VERSION)
Expand Down
10 changes: 6 additions & 4 deletions cli/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,14 @@ func commonFlags(f *pflag.FlagSet) {
f.StringVar(&cfg.ForceKubeVersion, "force-kube-version", "", "force a kubernetes version, rather than determining from the apiserver")
f.BoolVar(&cfg.NoVerifySig, "no-verify-signatures", false, "don't gpg-verify all downloaded addons")
f.StringVar(&cfg.GpgKeyringPath, "keyring", "/pubring.gpg", "path to the gpg keyring")
f.StringVar(&cfg.VersionManifestPath, "version-manifest", "/versions.yaml", "path to the version manifest file")
f.StringVar(&cfg.VersionManifestPath, "version-manifest", "", "path to the runtime-mappings manifest file")
f.StringVar(&verbose, "verbose", "info", "verbosity level")
}

// parseFlags parses CLI options, returning a populated configuration for the bootstrap agent
func parseFlags() (internal.Config, error) {
// parseFlags parses CLI options, returning a populated configuration for
// the bootstrap agent. It takes the path to the version manifest containing runtime
// mappings (consumed by hook logic and used as fallback by the bootstrapper).
func parseFlags(defaultRuntimeMappingsPath string) (internal.Config, error) {
zero := internal.Config{}

lvl, err := logrus.ParseLevel(verbose)
Expand Down Expand Up @@ -100,7 +102,7 @@ func parseFlags() (internal.Config, error) {
cfg.TorcxManifestURL = tmpl

if cfg.VersionManifestPath == "" {
return zero, errors.New("version-manifest required")
cfg.VersionManifestPath = defaultRuntimeMappingsPath
}

return cfg, nil
Expand Down
2 changes: 1 addition & 1 deletion cli/tectonic-torcx-bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func bootstrapInit() {
}

func runBootstrap(cmd *cobra.Command, args []string) error {
conf, err := parseFlags()
conf, err := parseFlags(internal.InstallerRuntimeMappings)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cli/tectonic-torcx-hook-pre.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func runHookPre(cmd *cobra.Command, args []string) error {
if err == nil {
logrus.AddHook(hook)
}
conf, err := parseFlags()
conf, err := parseFlags(internal.CluoRuntimeMappings)
if err != nil {
return err
}
Expand Down
8 changes: 7 additions & 1 deletion deploy/pre-reboot-hook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ spec:
name: tmp
- mountPath: /dev/log
name: dev-log
- mountPath: /etc/runtime-mappings.yaml
name: runtime-mappings-cm
subPath: runtime-mappings.yaml
env:
- name: NODE
valueFrom:
Expand Down Expand Up @@ -101,4 +104,7 @@ spec:
emptyDir: {}
- name: dev-log
hostPath:
path: /dev/log
path: /dev/log
- name: runtime-mappings-cm
configMap:
name: tectonic-torcx-runtime-mappings
20 changes: 20 additions & 0 deletions deploy/runtime-mappings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: tectonic-torcx-runtime-mappings
namespace: kube-system
data:
runtime-mappings.yaml: |
kind: VersionManifestV1
versions:
k8s:
1.6:
docker: [ "1.12"]
1.7:
# Kubernetes: https://github.com/kubernetes/kubernetes/blob/v1.9.0-alpha.2/CHANGELOG-1.7.md#external-dependency-version-information
# Latest CL stable: https://tectonic-torcx.release.core-os.net/manifests/amd64-usr/1520.8.0/torcx_manifest.json
docker: [ "1.12" ]
1.8:
# Kubernetes: https://github.com/kubernetes/kubernetes/blob/v1.9.0-alpha.2/CHANGELOG-1.8.md#external-dependency-version-information
# Latest CL stable: https://tectonic-torcx.release.core-os.net/manifests/amd64-usr/1520.8.0/torcx_manifest.json
docker: [ "17.03", "1.12"]
2 changes: 1 addition & 1 deletion internal/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (a *App) GatherState(localOnly bool, envPath string) error {
}
logrus.Infof("Detected Kubernetes version %s", a.K8sVersion)

a.DockerVersions, err = a.VersionFor("docker", a.K8sVersion)
a.DockerVersions, err = a.VersionFor(localOnly, "docker", a.K8sVersion)
if err != nil {
return err
}
Expand Down
86 changes: 79 additions & 7 deletions internal/versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,27 @@ import (

"github.com/coreos/go-semver/semver"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
yaml "gopkg.in/yaml.v2"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)

const KIND_VERSION_MANIFEST = "VersionManifestV1"
const (
// CluoRuntimeMappings is the default path for hook runtime-mappings (tectonic-cluo ConfigMap)
CluoRuntimeMappings = "/etc/runtime-mappings.yaml"
// InstallerRuntimeMappings is the default path for bootstrapper runtime-mappings (installer file)
InstallerRuntimeMappings = "/etc/kubernetes/installer/runtime-mappings.yaml"
// versionManifestKind is the current type for the runtime-mappings YAML object
versionManifestKind = "VersionManifestV1"
// configMapNamespace is the default namespace for runtime-mappings ConfigMap
configMapNamespace = "tectonic-system"
// configMapName is the default name for the runtime-mappings ConfigMap
configMapName = "tectonic-torcx-runtime-mappings"
// configMapKey is the default object/key in the runtime-mappings ConfigMap
configMapKey = "runtime-mappings.yaml"
)

type VersionManifest struct {
Kind string `yaml:"kind"`
Expand All @@ -36,8 +53,10 @@ type Dep map[string]map[string][]string
// VersionFor parses the version manifest file and returns the list of preferred
// package versions for a given k8s version. The returned value will never be
// empty if error is nil.
func (a *App) VersionFor(name, k8sVersion string) ([]string, error) {
m, err := a.GetVersionManifest()
func (a *App) VersionFor(localOnly bool, name, k8sVersion string) ([]string, error) {
// TODO(lucab): consider caching this manifest if we grow to
// more components other than docker.
m, err := a.GetVersionManifest(localOnly)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -81,19 +100,72 @@ func parseVersionManifest(data []byte) (*VersionManifest, error) {
return nil, errors.Wrap(err, "failed to parse version manifest")
}

if m.Kind != KIND_VERSION_MANIFEST {
if m.Kind != versionManifestKind {
return nil, fmt.Errorf("did not understand version kind %s", m.Kind)
}

return &m, nil
}

// GetVersionManifest parses the version manifest file supplied by the user.
func (a *App) GetVersionManifest() (*VersionManifest, error) {
data, err := ioutil.ReadFile(a.Conf.VersionManifestPath)
func (a *App) GetVersionManifest(localOnly bool) (*VersionManifest, error) {
path := a.Conf.VersionManifestPath
if path == "" {
return nil, errors.New("missing version manifest path")
}

// Conditionally try ConfigMap from api-server first (bootstrapper only)
if !localOnly {
logrus.Debug("Querying api-server for runtime mappings ConfigMap")
manifest, err := a.versionManifestFromAPIServer()
if err == nil {
return parseVersionManifest([]byte(manifest))
}
logrus.Warnf("Failed to query api-server for ConfigMap: %s", err)
}

// Source mappings from local file
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, errors.Wrap(err, "Failed to read version manifest")
return nil, errors.Wrapf(err, "Failed to read runtime mappings from %q", path)
}

return parseVersionManifest(data)
}

// versionManifestFromAPIServer connects to the APIServer and determines
// runtime mappings from the relevant ConfigMap.
func (a *App) versionManifestFromAPIServer() (string, error) {
config, err := clientcmd.BuildConfigFromFlags("", a.Conf.Kubeconfig)
if err != nil {
return "", errors.Wrap(err, "failed to build kubeconfig")
}

client, err := kubernetes.NewForConfig(config)
if err != nil {
return "", errors.Wrap(err, "failed to build kube client")
}

var versionManifest string
err = retry(3, 10, func() error {
cmi := client.ConfigMaps(configMapNamespace)
if cmi == nil {
return errors.Errorf("nil ConfigMapInterface for namespace %s", configMapNamespace)
}
cm, e := cmi.Get(configMapName, meta_v1.GetOptions{})
if e != nil {
return e
}
if cm == nil || cm.Data[configMapKey] == "" {
return errors.Errorf("missing entry %s/%s", configMapName, configMapKey)
}
versionManifest = cm.Data[configMapKey]
return nil
})
if err != nil {
return "", errors.Wrapf(err, "failed to get ConfigMap %s/%s", configMapNamespace, configMapName)
}
logrus.Debugf("Got %s from ConfigMap %s/%s", configMapKey, configMapNamespace, configMapName)

return versionManifest, nil
}
16 changes: 0 additions & 16 deletions versions.yaml

This file was deleted.