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

Create asset graph engine #120

Merged
merged 11 commits into from
Aug 25, 2018
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
19 changes: 18 additions & 1 deletion Documentation/design/installconfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,13 @@ type InstallConfig struct {
metav1.ObjectMeta `json:"metadata"`

// ClusterID is the ID of the cluster.
ClusterID uuid.UUID `json:"clusterID"`
ClusterID string `json:"clusterID"`

// Admin is the configuration for the admin user.
Admin Admin `json:"admin"`

// BaseDomain is the base domain to which the cluster should belong.
BaseDomain string `json:"baseDomain"`

// Networking defines the pod network provider in the cluster.
Networking `json:"networking"`
Expand All @@ -253,6 +259,17 @@ type InstallConfig struct {

// only one of the platform configuration should be set
Platform `json:"platform"`

// License is an OpenShift license needed to install a cluster.
License string `json:"license"`

// PullSecret is the secret to use when pulling images.
PullSecret string `json:"pullSecret"`
}

type Admin struct {
Email string `json:"email"`
Password string `json:"password"`
}

type Platform struct {
Expand Down
44 changes: 44 additions & 0 deletions cmd/openshift-install/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main
Copy link
Contributor

Choose a reason for hiding this comment

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

Golint comments: should have a package comment, unless it's in another file for this package. More info.


import (
"os"

log "github.com/Sirupsen/logrus"
"gopkg.in/alecthomas/kingpin.v2"

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

var (
installConfigCommand = kingpin.Command("install-config", "Generate the Install Config asset")

dirFlag = kingpin.Flag("dir", "assets directory").Default(".").String()
logLevel = kingpin.Flag("log-level", "log level (e.g. \"debug\")").Default("info").Enum("debug", "info", "warn", "error", "fatal", "panic")
)

func main() {
command := kingpin.Parse()

assetStock := stock.EstablishStock(*dirFlag)

var targetAsset asset.Asset

switch command {
case installConfigCommand.FullCommand():
targetAsset = assetStock.InstallConfig()
}

l, err := log.ParseLevel(*logLevel)
if err != nil {
// By definition we should never enter this condition since kingpin should be guarding against incorrect values.
log.Fatalf("invalid log-level: %v", err)
}
log.SetLevel(l)

assetStore := &asset.StoreImpl{}
if _, err := assetStore.Fetch(targetAsset); err != nil {
log.Fatalf("failed to generate asset: %v", err)
os.Exit(1)
}
}
18 changes: 16 additions & 2 deletions glide.lock

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

10 changes: 10 additions & 0 deletions pkg/asset/asset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package asset
Copy link
Contributor

Choose a reason for hiding this comment

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

Golint comments: should have a package comment, unless it's in another file for this package. More info.


// Asset used to install OpenShift.
type Asset interface {
// Dependencies returns the assets upon which this asset directly depends.
Dependencies() []Asset

// Generate generates this asset given the states of its dependent assets.
Generate(map[Asset]*State) (*State, error)
}
25 changes: 25 additions & 0 deletions pkg/asset/installconfig/clusterid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package installconfig
Copy link
Contributor

Choose a reason for hiding this comment

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

Golint comments: should have a package comment, unless it's in another file for this package. More info.


import (
"github.com/pborman/uuid"

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

type clusterID struct{}

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

// Dependencies returns no dependencies.
func (a *clusterID) Dependencies() []asset.Asset {
return []asset.Asset{}
}

// Generate generates a new UUID
func (a *clusterID) Generate(map[asset.Asset]*asset.State) (*asset.State, error) {
return &asset.State{
Contents: []asset.Content{
{Data: []byte(uuid.NewUUID().String())},

Choose a reason for hiding this comment

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

Note that uuid.NewUUID uses a time-based seed to generate the random ID. You can use the apimachinery util instead - https://github.com/kubernetes/apimachinery/blob/017bf4f8f5884203a401400e511f4c8fc2eded21/pkg/util/uuid/uuid.go#L30

Copy link
Member

Choose a reason for hiding this comment

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

Note that uuid.NewUUID uses a time-based seed to generate the random ID.

I think we should just switch to asking for a version 4 UUID. It looks like that's []byte(uuid.New()) (NewUUID is asking for a version 1 UUID).

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point, I can address this when rebasing my pr #145

},
}, nil
}
100 changes: 100 additions & 0 deletions pkg/asset/installconfig/installconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package installconfig
Copy link
Contributor

Choose a reason for hiding this comment

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

Golint comments: should have a package comment, unless it's in another file for this package. More info.


import (
"fmt"
"path/filepath"

"github.com/ghodss/yaml"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

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

// installConfig generates the install-config.yml file.
type installConfig struct {
assetStock Stock
directory string
}

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

// Dependencies returns all of the dependencies directly needed by an
// installConfig asset.
func (a *installConfig) Dependencies() []asset.Asset {
return []asset.Asset{
a.assetStock.ClusterID(),
a.assetStock.EmailAddress(),
a.assetStock.Password(),
a.assetStock.BaseDomain(),
a.assetStock.ClusterName(),
a.assetStock.License(),
a.assetStock.PullSecret(),
a.assetStock.Platform(),
}
}

// Generate generates the install-config.yml file.
func (a *installConfig) Generate(dependencies map[asset.Asset]*asset.State) (*asset.State, error) {
clusterID := string(dependencies[a.assetStock.ClusterID()].Contents[0].Data)
emailAddress := string(dependencies[a.assetStock.EmailAddress()].Contents[0].Data)
password := string(dependencies[a.assetStock.Password()].Contents[0].Data)
baseDomain := string(dependencies[a.assetStock.BaseDomain()].Contents[0].Data)
clusterName := string(dependencies[a.assetStock.ClusterName()].Contents[0].Data)
license := string(dependencies[a.assetStock.License()].Contents[0].Data)
pullSecret := string(dependencies[a.assetStock.PullSecret()].Contents[0].Data)

installConfig := types.InstallConfig{
ObjectMeta: metav1.ObjectMeta{
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need objectmeta if it's just for ClusterName?
I am not strongly against this though, but might be good if we can add some docs in the object, so it's easier for other folks to find the ClusterName

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know what the plans are for objectmeta. It was defined that way in https://github.com/openshift/installer/blob/master/Documentation/design/installconfig.md. I also don't have a strong opinion one way or the other whether the Cluster Name is placed in the objectmeta or in a separate field.

Name: clusterName,
},
ClusterID: clusterID,
Admin: types.Admin{
Email: emailAddress,
Password: password,
},
BaseDomain: baseDomain,
License: license,
PullSecret: pullSecret,
}

platformState := dependencies[a.assetStock.Platform()]
platform := string(platformState.Contents[0].Data)
switch platform {
case AWSPlatformType:
region := string(platformState.Contents[1].Data)
keyPairName := string(platformState.Contents[2].Data)
Copy link
Member

Choose a reason for hiding this comment

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

This is probably stale after #127. Can we move this out of AWSPlatformType and make it sshKey with a string for the pubkey?

installConfig.AWS = &types.AWSPlatform{
Region: region,
KeyPairName: keyPairName,
}
case LibvirtPlatformType:
uri := string(platformState.Contents[1].Data)
sshKey := string(platformState.Contents[2].Data)
installConfig.Libvirt = &types.LibvirtPlatform{
URI: uri,
SSHKey: sshKey,
}
default:
return nil, fmt.Errorf("unknown platform type %q", platform)
}

data, err := yaml.Marshal(installConfig)
Copy link
Contributor

Choose a reason for hiding this comment

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

From #145 (comment):

I think many packages will need to perform this. so either move it to a common helpfer func (ideally it can just take the asset.State and iterate over the contents) or make the Store to do it? But I am aware that some targets won't need to write stuff into disk (e.g. the targetable assets like Cluster)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds reasonable.

if err != nil {
return nil, err
}

state := &asset.State{
Contents: []asset.Content{
{
Name: filepath.Join(a.directory, "install-config.yml"),
Data: data,
},
},
}

state.PersistToFile()

return state, nil
}
Loading