Skip to content

Commit

Permalink
WIP: pkg/rhcos/updatepayload: Extract RHCOS build from update payload
Browse files Browse the repository at this point in the history
Since e2b31b2 (bootkube: Supply machine-os-content to MCO,
2019-01-29, openshift#1149), we have been using the machine-os-content image to
seed the machine-config operator.  With this commit, use the RHCOS
build ID from that image's annotations to calculate our AMI, etc. as
well.  This gives one less degree of freedom for breaking things ;).
Users who want to test clusters based on a different RHCOS build
should bump the value in their update payload, just like users testing
operator updates and other changes.

This is a WIP until I look into signature verification.
  • Loading branch information
wking committed Feb 21, 2019
1 parent 87ede7c commit 2561c60
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 81 deletions.
6 changes: 1 addition & 5 deletions hack/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,7 @@ release)
TAGS="${TAGS} release"
if test -n "${RELEASE_IMAGE}"
then
LDFLAGS="${LDFLAGS} -X github.com/openshift/installer/pkg/asset/ignition/bootstrap.defaultReleaseImage=${RELEASE_IMAGE}"
fi
if test -n "${RHCOS_BUILD_NAME}"
then
LDFLAGS="${LDFLAGS} -X github.com/openshift/installer/pkg/rhcos.buildName=${RHCOS_BUILD_NAME}"
LDFLAGS="${LDFLAGS} -X github.com/openshift/installer/pkg/asset/release.defaultReleaseImage=${RELEASE_IMAGE}"
fi
if test "${SKIP_GENERATION}" != y
then
Expand Down
21 changes: 7 additions & 14 deletions pkg/asset/ignition/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/openshift/installer/pkg/asset/kubeconfig"
"github.com/openshift/installer/pkg/asset/machines"
"github.com/openshift/installer/pkg/asset/manifests"
"github.com/openshift/installer/pkg/asset/release"
"github.com/openshift/installer/pkg/asset/tls"
"github.com/openshift/installer/pkg/types"
)
Expand All @@ -36,10 +37,6 @@ const (
ignitionUser = "core"
)

var (
defaultReleaseImage = "registry.svc.ci.openshift.org/openshift/origin-release:v4.0"
)

// bootstrapTemplateData is the data to use to replace values in bootstrap
// template files.
type bootstrapTemplateData struct {
Expand All @@ -62,6 +59,7 @@ var _ asset.WritableAsset = (*Bootstrap)(nil)
func (a *Bootstrap) Dependencies() []asset.Asset {
return []asset.Asset{
&installconfig.InstallConfig{},
new(release.Release),
&tls.RootCA{},
&tls.EtcdCA{},
&tls.KubeCA{},
Expand All @@ -85,9 +83,10 @@ func (a *Bootstrap) Dependencies() []asset.Asset {
// Generate generates the ignition config for the Bootstrap asset.
func (a *Bootstrap) Generate(dependencies asset.Parents) error {
installConfig := &installconfig.InstallConfig{}
dependencies.Get(installConfig)
release := new(release.Release)
dependencies.Get(installConfig, release)

templateData, err := a.getTemplateData(installConfig.Config)
templateData, err := a.getTemplateData(installConfig.Config, string(*release))
if err != nil {
return errors.Wrap(err, "failed to get bootstrap templates")
}
Expand Down Expand Up @@ -139,23 +138,17 @@ func (a *Bootstrap) Files() []*asset.File {
}

// getTemplateData returns the data to use to execute bootstrap templates.
func (a *Bootstrap) getTemplateData(installConfig *types.InstallConfig) (*bootstrapTemplateData, error) {
func (a *Bootstrap) getTemplateData(installConfig *types.InstallConfig, release string) (*bootstrapTemplateData, error) {
etcdEndpoints := make([]string, *installConfig.ControlPlane.Replicas)
for i := range etcdEndpoints {
etcdEndpoints[i] = fmt.Sprintf("https://etcd-%d.%s:2379", i, installConfig.ClusterDomain())
}

releaseImage := defaultReleaseImage
if ri, ok := os.LookupEnv("OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE"); ok && ri != "" {
logrus.Warn("Found override for ReleaseImage. Please be warned, this is not advised")
releaseImage = ri
}

return &bootstrapTemplateData{
EtcdCertSignerImage: etcdCertSignerImage,
EtcdctlImage: etcdctlImage,
PullSecret: installConfig.PullSecret,
ReleaseImage: releaseImage,
ReleaseImage: release,
EtcdCluster: strings.Join(etcdEndpoints, ","),
}, nil
}
Expand Down
41 changes: 41 additions & 0 deletions pkg/asset/release/release.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Package release contains assets for the release image (also known
// as the update payload).
package release

import (
"os"

"github.com/sirupsen/logrus"

"github.com/openshift/installer/pkg/asset"
)

var (
defaultReleaseImage = "registry.svc.ci.openshift.org/openshift/origin-release:v4.0"
)

// Release is the pull-spec for the release image.
type Release string

var _ asset.Asset = (*Release)(nil)

// Name returns the human-friendly name of the asset.
func (i *Release) Name() string {
return "Release"
}

// Dependencies returns no dependencies.
func (i *Release) Dependencies() []asset.Asset {
return nil
}

// Generate the release image.
func (r *Release) Generate(p asset.Parents) error {
releaseImage := defaultReleaseImage
if ri := os.Getenv("OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE"); ri != "" {
logrus.Warn("Found override for ReleaseImage. Please be warned, this is not advised")
releaseImage = ri
}
*r = Release(releaseImage)
return nil
}
21 changes: 15 additions & 6 deletions pkg/asset/rhcos/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import (

"github.com/openshift/installer/pkg/asset"
"github.com/openshift/installer/pkg/asset/installconfig"
"github.com/openshift/installer/pkg/asset/release"
"github.com/openshift/installer/pkg/rhcos"
"github.com/openshift/installer/pkg/rhcos/updatepayload"
"github.com/openshift/installer/pkg/types/aws"
"github.com/openshift/installer/pkg/types/libvirt"
"github.com/openshift/installer/pkg/types/none"
Expand All @@ -30,10 +32,11 @@ func (i *Image) Name() string {
return "Image"
}

// Dependencies returns no dependencies.
// Dependencies returns the assets on which the Image asset depends.
func (i *Image) Dependencies() []asset.Asset {
return []asset.Asset{
&installconfig.InstallConfig{},
new(release.Release),
}
}

Expand All @@ -46,18 +49,24 @@ func (i *Image) Generate(p asset.Parents) error {
}

ic := &installconfig.InstallConfig{}
p.Get(ic)
release := new(release.Release)
p.Get(ic, release)
config := ic.Config

ctx := context.TODO()
build, err := updatepayload.RHCOSBuild(ctx, string(*release))
if err != nil {
return err
}

var osimage string
var err error
ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
switch config.Platform.Name() {
case aws.Name:
osimage, err = rhcos.AMI(ctx, rhcos.DefaultChannel, config.Platform.AWS.Region)
osimage, err = rhcos.AMI(ctx, rhcos.DefaultChannel, build, config.Platform.AWS.Region)
case libvirt.Name:
osimage, err = rhcos.QEMU(ctx, rhcos.DefaultChannel)
osimage, err = rhcos.QEMU(ctx, rhcos.DefaultChannel, build)
case openstack.Name:
osimage = "rhcos"
case none.Name:
Expand Down
4 changes: 2 additions & 2 deletions pkg/rhcos/ami.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
)

// AMI fetches the HVM AMI ID of the latest Red Hat CoreOS release.
func AMI(ctx context.Context, channel, region string) (string, error) {
meta, err := fetchLatestMetadata(ctx, channel)
func AMI(ctx context.Context, channel, build, region string) (string, error) {
meta, err := fetchMetadata(ctx, channel, build)
if err != nil {
return "", errors.Wrap(err, "failed to fetch RHCOS metadata")
}
Expand Down
53 changes: 1 addition & 52 deletions pkg/rhcos/builds.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ var (
// DefaultChannel is the default RHCOS channel for the cluster.
DefaultChannel = "maipo"

// buildName is the name of the build in the channel that will be picked up
// empty string means the first one in the build list (latest) will be used
buildName = ""

baseURL = "https://releases-rhcos.svc.ci.openshift.org/storage/releases"
)

Expand All @@ -36,16 +32,7 @@ type metadata struct {
OSTreeVersion string `json:"ostree-version"`
}

func fetchLatestMetadata(ctx context.Context, channel string) (metadata, error) {
build := buildName
var err error
if build == "" {
build, err = fetchLatestBuild(ctx, channel)
if err != nil {
return metadata{}, errors.Wrap(err, "failed to fetch latest build")
}
}

func fetchMetadata(ctx context.Context, channel string, build string) (metadata, error) {
url := fmt.Sprintf("%s/%s/%s/meta.json", baseURL, channel, build)
logrus.Debugf("Fetching RHCOS metadata from %q", url)
req, err := http.NewRequest("GET", url, nil)
Expand Down Expand Up @@ -76,41 +63,3 @@ func fetchLatestMetadata(ctx context.Context, channel string) (metadata, error)

return meta, nil
}

func fetchLatestBuild(ctx context.Context, channel string) (string, error) {
url := fmt.Sprintf("%s/%s/builds.json", baseURL, channel)
logrus.Debugf("Fetching RHCOS builds from %q", url)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", errors.Wrap(err, "failed to build request")
}

client := &http.Client{}
resp, err := client.Do(req.WithContext(ctx))
if err != nil {
return "", errors.Wrap(err, "failed to fetch builds")
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return "", errors.Errorf("incorrect HTTP response (%s)", resp.Status)
}

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", errors.Wrap(err, "failed to read HTTP response")
}

var builds struct {
Builds []string `json:"builds"`
}
if err := json.Unmarshal(body, &builds); err != nil {
return "", errors.Wrap(err, "failed to parse HTTP response")
}

if len(builds.Builds) == 0 {
return "", errors.Errorf("no builds found")
}

return builds.Builds[0], nil
}
4 changes: 2 additions & 2 deletions pkg/rhcos/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
)

// QEMU fetches the URL of the latest Red Hat CoreOS release.
func QEMU(ctx context.Context, channel string) (string, error) {
meta, err := fetchLatestMetadata(ctx, channel)
func QEMU(ctx context.Context, channel string, build string) (string, error) {
meta, err := fetchMetadata(ctx, channel, build)
if err != nil {
return "", errors.Wrap(err, "failed to fetch RHCOS metadata")
}
Expand Down
Loading

0 comments on commit 2561c60

Please sign in to comment.