Skip to content
Snippets Groups Projects
Commit 68fcbd21 authored by bryanl's avatar bryanl
Browse files

Extract ksonnet generator


extracts ksonnet generator to a new package to make it easier to incorporate in new code

Signed-off-by: default avatarbryanl <bryanliles@gmail.com>
parent 861c2d12
No related branches found
No related tags found
No related merge requests found
package generator
import (
"encoding/json"
"github.com/ksonnet/ksonnet-lib/ksonnet-gen/ksonnet"
"github.com/ksonnet/ksonnet-lib/ksonnet-gen/kubespec"
"github.com/ksonnet/ksonnet-lib/ksonnet-gen/kubeversion"
log "github.com/sirupsen/logrus"
)
var (
// ksonnetEmitter is the function which emits the ksonnet standard library.
ksonnetEmitter = ksonnet.Emit
)
// KsonnetLib is the ksonnet standard library for a version of swagger.
type KsonnetLib struct {
// K is ksonnet extensions.
K []byte
// K is the generated ksonnet library.
K8s []byte
// Swagger is the swagger JSON used to generate the library.
Swagger []byte
// Version is the API version of the swagger.
Version string
}
// Ksonnet generates the ksonnet standard library or returns an error if there was
// a problem.
func Ksonnet(swaggerData []byte) (*KsonnetLib, error) {
// Deserialize the API object.
s := kubespec.APISpec{}
if err := json.Unmarshal(swaggerData, &s); err != nil {
return nil, err
}
s.Text = swaggerData
// Emit Jsonnet code.
extensionsLibData, k8sLibData, err := ksonnetEmitter(&s, nil, nil)
if err != nil {
return nil, err
}
// Warn where the Kubernetes version is currently only supported as Beta.
if kubeversion.Beta(s.Info.Version) {
log.Warnf(`!
============================================================================================
Kubernetes version %s is currently supported as Beta; you may encounter unexpected behavior
============================================================================================`, s.Info.Version)
}
kl := &KsonnetLib{
K: extensionsLibData,
K8s: k8sLibData,
Swagger: swaggerData,
Version: s.Info.Version,
}
return kl, nil
}
package generator
import (
"errors"
"testing"
"github.com/ksonnet/ksonnet-lib/ksonnet-gen/kubespec"
)
func TestKsonnet(t *testing.T) {
ogEmitter := ksonnetEmitter
defer func() {
ksonnetEmitter = ogEmitter
}()
var (
ext = []byte("k")
lib = []byte("k8s")
successfulEmit = func(*kubespec.APISpec, *string, *string) ([]byte, []byte, error) {
return ext, lib, nil
}
failureEmit = func(*kubespec.APISpec, *string, *string) ([]byte, []byte, error) {
return nil, nil, errors.New("failure")
}
v170swagger = []byte(`{"info":{"version":"v1.7.0"}}`)
v180swagger = []byte(`{"info":{"version":"v1.8.0"}}`)
)
cases := []struct {
name string
emitter func(*kubespec.APISpec, *string, *string) ([]byte, []byte, error)
swaggerData []byte
version string
isErr bool
}{
{
name: "valid swagger",
emitter: successfulEmit,
swaggerData: v170swagger,
version: "v1.7.0",
},
{
name: "invalid swagger",
swaggerData: []byte(`{`),
isErr: true,
},
{
name: "emitter error",
emitter: failureEmit,
swaggerData: v170swagger,
isErr: true,
},
{
name: "valid beta swagger",
emitter: successfulEmit,
swaggerData: v180swagger,
version: "v1.8.0",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
ksonnetEmitter = tc.emitter
kl, err := Ksonnet(tc.swaggerData)
if tc.isErr {
if err == nil {
t.Fatal("Ksonnet() should have returned an error")
}
} else {
if err != nil {
t.Fatal("Ksonnet() returned unexpected error")
}
if got, expected := string(kl.K), string(ext); got != expected {
t.Errorf("Ksonnet() K = %s; expected = %s", got, expected)
}
if got, expected := string(kl.K8s), string(lib); got != expected {
t.Errorf("Ksonnet() K8s = %s; expected = %s", got, expected)
}
if got, expected := string(kl.Swagger), string(tc.swaggerData); got != expected {
t.Errorf("Ksonnet() Swagger = %s; expected = %s", got, expected)
}
if got, expected := string(kl.Version), tc.version; got != expected {
t.Errorf("Ksonnet() Version = %s; expected = %s", got, expected)
}
}
})
}
}
......@@ -42,11 +42,11 @@ type clusterSpecFile struct {
fs afero.Fs
}
func (cs *clusterSpecFile) data() ([]byte, error) {
func (cs *clusterSpecFile) OpenAPI() ([]byte, error) {
return afero.ReadFile(cs.fs, string(cs.specPath))
}
func (cs *clusterSpecFile) resource() string {
func (cs *clusterSpecFile) Resource() string {
return string(cs.specPath)
}
......@@ -54,11 +54,11 @@ type clusterSpecLive struct {
apiServerURL string
}
func (cs *clusterSpecLive) data() ([]byte, error) {
func (cs *clusterSpecLive) OpenAPI() ([]byte, error) {
return nil, fmt.Errorf("Initializing from OpenAPI spec in live cluster is not implemented")
}
func (cs *clusterSpecLive) resource() string {
func (cs *clusterSpecLive) Resource() string {
return string(cs.apiServerURL)
}
......@@ -66,7 +66,7 @@ type clusterSpecVersion struct {
k8sVersion string
}
func (cs *clusterSpecVersion) data() ([]byte, error) {
func (cs *clusterSpecVersion) OpenAPI() ([]byte, error) {
versionURL := fmt.Sprintf(k8sVersionURLTemplate, cs.k8sVersion)
resp, err := http.Get(versionURL)
if err != nil {
......@@ -83,6 +83,6 @@ func (cs *clusterSpecVersion) data() ([]byte, error) {
return ioutil.ReadAll(resp.Body)
}
func (cs *clusterSpecVersion) resource() string {
func (cs *clusterSpecVersion) Resource() string {
return string(cs.k8sVersion)
}
......@@ -23,8 +23,8 @@ func TestClusterSpecParsingSuccess(t *testing.T) {
t.Errorf("Failed to parse spec: %v", err)
}
parsedResource := parsed.resource()
targetResource := test.target.resource()
parsedResource := parsed.Resource()
targetResource := test.target.Resource()
switch pt := parsed.(type) {
case *clusterSpecLive:
......
......@@ -27,9 +27,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/afero"
"github.com/ksonnet/ksonnet-lib/ksonnet-gen/ksonnet"
"github.com/ksonnet/ksonnet-lib/ksonnet-gen/kubespec"
"github.com/ksonnet/ksonnet-lib/ksonnet-gen/kubeversion"
"github.com/ksonnet/ksonnet/generator"
param "github.com/ksonnet/ksonnet/metadata/params"
"github.com/ksonnet/ksonnet/utils"
)
......@@ -75,13 +73,18 @@ type EnvironmentSpec struct {
}
func (m *manager) CreateEnvironment(name, server, namespace string, spec ClusterSpec) error {
extensionsLibData, k8sLibData, specData, err := m.generateKsonnetLibData(spec)
b, err := spec.OpenAPI()
if err != nil {
return err
}
kl, err := generator.Ksonnet(b)
if err != nil {
log.Debugf("Failed to write '%s'", specFilename)
return err
}
err = m.createEnvironment(name, server, namespace, extensionsLibData, k8sLibData, specData)
err = m.createEnvironment(name, server, namespace, kl.K, kl.K8s, kl.Swagger)
if err == nil {
log.Infof("Environment '%s' pointing to namespace '%s' and server address at '%s' successfully created", name, namespace, server)
}
......@@ -497,42 +500,6 @@ func (m *manager) cleanEmptyParentDirs(name string) error {
return nil
}
func (m *manager) generateKsonnetLibData(spec ClusterSpec) ([]byte, []byte, []byte, error) {
// Get cluster specification data, possibly from the network.
text, err := spec.data()
if err != nil {
return nil, nil, nil, err
}
ksonnetLibDir := appendToAbsPath(m.environmentsPath, defaultEnvName)
// Deserialize the API object.
s := kubespec.APISpec{}
err = json.Unmarshal(text, &s)
if err != nil {
return nil, nil, nil, err
}
s.Text = text
s.FilePath = filepath.Dir(string(ksonnetLibDir))
// Emit Jsonnet code.
extensionsLibData, k8sLibData, err := ksonnet.Emit(&s, nil, nil)
if err != nil {
return nil, nil, nil, err
}
// Warn where the Kubernetes version is currently only supported as Beta.
if kubeversion.Beta(s.Info.Version) {
log.Warnf(`!
============================================================================================
Kubernetes version %s is currently supported as Beta; you may encounter unexpected behavior
============================================================================================`, s.Info.Version)
}
return extensionsLibData, k8sLibData, text, nil
}
func (m *manager) generateOverrideData() []byte {
const (
relBaseLibsonnetPath = "../" + baseLibsonnetFile
......
......@@ -119,8 +119,8 @@ func Init(name string, rootPath AbsPath, spec ClusterSpec, serverURI, namespace
// OpenAPI spec in some file, or consulting the OpenAPI spec released in a
// specific version of Kubernetes.
type ClusterSpec interface {
data() ([]byte, error)
resource() string // For testing parsing logic.
OpenAPI() ([]byte, error)
Resource() string // For testing parsing logic.
}
// ParseClusterSpec will parse a cluster spec flag and output a well-formed
......
......@@ -21,6 +21,7 @@ import (
"path"
"path/filepath"
"github.com/ksonnet/ksonnet/generator"
"github.com/ksonnet/ksonnet/metadata/app"
param "github.com/ksonnet/ksonnet/metadata/params"
"github.com/ksonnet/ksonnet/metadata/registry"
......@@ -117,7 +118,12 @@ func initManager(name string, rootPath AbsPath, spec ClusterSpec, serverURI, nam
// either (e.g., GET'ing the spec from a live cluster returns 404) does not
// result in a partially-initialized directory structure.
//
extensionsLibData, k8sLibData, specData, err := m.generateKsonnetLibData(spec)
b, err := spec.OpenAPI()
if err != nil {
return nil, err
}
kl, err := generator.Ksonnet(b)
if err != nil {
return nil, err
}
......@@ -149,7 +155,7 @@ func initManager(name string, rootPath AbsPath, spec ClusterSpec, serverURI, nam
// Initialize environment, and cache specification data.
if serverURI != nil {
err := m.createEnvironment(defaultEnvName, *serverURI, *namespace, extensionsLibData, k8sLibData, specData)
err := m.createEnvironment(defaultEnvName, *serverURI, *namespace, kl.K, kl.K8s, kl.Swagger)
if err != nil {
return nil, errorOnCreateFailure(name, err)
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment