Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
H
helm3
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
helm3
Commits
51bbfafc
Commit
51bbfafc
authored
Mar 23, 2016
by
Jack Greenfield
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #440 from jackgr/manager
Second round of refactoring for Manager
parents
91a007cf
3da6a66c
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
286 additions
and
938 deletions
+286
-938
deployments.go
cmd/manager/deployments.go
+79
-101
expander.go
cmd/manager/manager/expander.go
+16
-1
expander_test.go
cmd/manager/manager/expander_test.go
+1
-29
manager.go
cmd/manager/manager/manager.go
+66
-113
manager_test.go
cmd/manager/manager/manager_test.go
+37
-37
typeresolver.go
cmd/manager/manager/typeresolver.go
+0
-245
typeresolver_test.go
cmd/manager/manager/typeresolver_test.go
+0
-328
persistent.go
cmd/manager/repository/persistent/persistent.go
+12
-12
persistent_test.go
cmd/manager/repository/persistent/persistent_test.go
+2
-2
repository.go
cmd/manager/repository/repository.go
+4
-4
test_common.go
cmd/manager/repository/test_common.go
+18
-18
transient.go
cmd/manager/repository/transient/transient.go
+16
-16
transient_test.go
cmd/manager/repository/transient/transient_test.go
+2
-2
context.go
cmd/manager/router/context.go
+2
-2
testutil.go
cmd/manager/testutil.go
+29
-26
types.go
pkg/common/types.go
+2
-2
No files found.
cmd/manager/deployments.go
View file @
51bbfafc
...
...
@@ -38,7 +38,7 @@ import (
"github.com/kubernetes/helm/cmd/manager/router"
"github.com/kubernetes/helm/pkg/common"
"github.com/kubernetes/helm/pkg/httputil"
"github.com/kubernetes/helm/pkg/re
gistry
"
"github.com/kubernetes/helm/pkg/re
po
"
"github.com/kubernetes/helm/pkg/util"
)
...
...
@@ -66,16 +66,18 @@ func registerDeploymentRoutes(c *router.Context, h *router.Handler) {
h
.
Add
(
"GET /deployments/*/manifests"
,
listManifestsHandlerFunc
)
h
.
Add
(
"GET /deployments/*/manifests/*"
,
getManifestHandlerFunc
)
h
.
Add
(
"POST /expand"
,
expandHandlerFunc
)
h
.
Add
(
"GET /types"
,
listTypesHandlerFunc
)
h
.
Add
(
"GET /types/*/instances"
,
listTypeInstancesHandlerFunc
)
h
.
Add
(
"GET /types/*/registry"
,
getRegistryForTypeHandlerFunc
)
h
.
Add
(
"GET /types/*/metadata"
,
getMetadataForTypeHandlerFunc
)
h
.
Add
(
"GET /registries"
,
listRegistriesHandlerFunc
)
h
.
Add
(
"GET /registries/*"
,
getRegistryHandlerFunc
)
h
.
Add
(
"POST /registries/*"
,
createRegistryHandlerFunc
)
h
.
Add
(
"GET /registries/*/types"
,
listRegistryTypesHandlerFunc
)
h
.
Add
(
"GET /registries/*/types/*"
,
getDownloadURLsHandlerFunc
)
h
.
Add
(
"GET /registries/*/download"
,
getFileHandlerFunc
)
h
.
Add
(
"GET /charts"
,
listChartsHandlerFunc
)
h
.
Add
(
"GET /charts/*/instances"
,
listChartInstancesHandlerFunc
)
h
.
Add
(
"GET /charts/*/repository"
,
getRepoForChartHandlerFunc
)
h
.
Add
(
"GET /charts/*/metadata"
,
getMetadataForChartHandlerFunc
)
h
.
Add
(
"GET /charts/*"
,
getChartHandlerFunc
)
// TODO: Refactor these commented out routes
// h.Add("GET /repositories/*", getRepoHandlerFunc)
// h.Add("POST /repositories/*", createRepoHandlerFunc)
h
.
Add
(
"GET /repositories/*/charts"
,
listRepositoryChartsHandlerFunc
)
h
.
Add
(
"GET /repositories/*/charts/*"
,
getRepositoryChartHandlerFunc
)
h
.
Add
(
"POST /credentials/*"
,
createCredentialHandlerFunc
)
h
.
Add
(
"GET /credentials/*"
,
getCredentialHandlerFunc
)
}
...
...
@@ -89,20 +91,20 @@ func healthz(w http.ResponseWriter, r *http.Request, c *router.Context) error {
}
func
setupDependencies
(
c
*
router
.
Context
)
error
{
var
credentialProvider
common
.
CredentialProvider
var
credentialProvider
repo
.
I
CredentialProvider
if
c
.
Config
.
CredentialFile
!=
""
{
if
c
.
Config
.
CredentialSecrets
{
return
errors
.
New
(
"Both credentialFile and credentialSecrets are set"
)
}
var
err
error
credentialProvider
,
err
=
re
gistry
.
NewFilebasedCredentialProvider
(
c
.
Config
.
CredentialFile
)
credentialProvider
,
err
=
re
po
.
NewFilebasedCredentialProvider
(
c
.
Config
.
CredentialFile
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"cannot create credential provider %s: %s"
,
c
.
Config
.
CredentialFile
,
err
)
}
}
else
if
*
credentialSecrets
{
credentialProvider
=
re
gistry
.
NewSecretsCredentialProvider
()
credentialProvider
=
re
po
.
NewSecretsCredentialProvider
()
}
else
{
credentialProvider
=
re
gistry
.
NewInmemCredentialProvider
()
credentialProvider
=
re
po
.
NewInmemCredentialProvider
()
}
c
.
CredentialProvider
=
credentialProvider
c
.
Manager
=
newManager
(
c
)
...
...
@@ -115,14 +117,14 @@ const deployerPort = "8080"
func
newManager
(
c
*
router
.
Context
)
manager
.
Manager
{
cfg
:=
c
.
Config
service
:=
re
gistry
.
NewInmemRegistry
Service
()
registryProvider
:=
registry
.
NewDefaultRegistryProvider
(
c
.
CredentialProvider
,
service
)
re
solver
:=
manager
.
NewTypeResolver
(
registryProvider
,
util
.
DefaultHTTPClient
()
)
expander
:=
manager
.
NewExpander
(
getServiceURL
(
cfg
.
ExpanderURL
,
cfg
.
ExpanderName
,
expanderPort
)
,
resolver
)
service
:=
re
po
.
NewInmemRepo
Service
()
cp
:=
c
.
CredentialProvider
re
poProvider
:=
repo
.
NewRepoProvider
(
service
,
repo
.
NewGCSRepoProvider
(
cp
),
cp
)
expander
:=
manager
.
NewExpander
(
getServiceURL
(
cfg
.
ExpanderURL
,
cfg
.
ExpanderName
,
expanderPort
))
deployer
:=
manager
.
NewDeployer
(
getServiceURL
(
cfg
.
DeployerURL
,
cfg
.
DeployerName
,
deployerPort
))
address
:=
strings
.
TrimPrefix
(
getServiceURL
(
cfg
.
MongoAddress
,
cfg
.
MongoName
,
cfg
.
MongoPort
),
"http://"
)
repository
:=
createRepository
(
address
)
return
manager
.
NewManager
(
expander
,
deployer
,
repository
,
re
gistry
Provider
,
service
,
c
.
CredentialProvider
)
return
manager
.
NewManager
(
expander
,
deployer
,
repository
,
re
po
Provider
,
service
,
c
.
CredentialProvider
)
}
func
createRepository
(
address
string
)
repository
.
Repository
{
...
...
@@ -369,10 +371,10 @@ func expandHandlerFunc(w http.ResponseWriter, r *http.Request, c *router.Context
// Putting Type handlers here for now because deployments.go
// currently owns its own Manager backend and doesn't like to share.
func
list
Type
sHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: list
type
s"
func
list
Chart
sHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: list
chart
s"
util
.
LogHandlerEntry
(
handler
,
r
)
types
,
err
:=
c
.
Manager
.
List
Type
s
()
types
,
err
:=
c
.
Manager
.
List
Chart
s
()
if
err
!=
nil
{
httputil
.
BadRequest
(
w
,
r
,
err
)
return
nil
...
...
@@ -382,15 +384,15 @@ func listTypesHandlerFunc(w http.ResponseWriter, r *http.Request, c *router.Cont
return
nil
}
func
list
Type
InstancesHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: list instances"
func
list
Chart
InstancesHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: list
chart
instances"
util
.
LogHandlerEntry
(
handler
,
r
)
type
Name
,
err
:=
pos
(
w
,
r
,
2
)
chart
Name
,
err
:=
pos
(
w
,
r
,
2
)
if
err
!=
nil
{
return
err
}
instances
,
err
:=
c
.
Manager
.
List
Instances
(
type
Name
)
instances
,
err
:=
c
.
Manager
.
List
ChartInstances
(
chart
Name
)
if
err
!=
nil
{
httputil
.
BadRequest
(
w
,
r
,
err
)
return
nil
...
...
@@ -400,33 +402,33 @@ func listTypeInstancesHandlerFunc(w http.ResponseWriter, r *http.Request, c *rou
return
nil
}
func
getRe
gistryForType
HandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: get
type registry
"
func
getRe
poForChart
HandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: get
repository for chart
"
util
.
LogHandlerEntry
(
handler
,
r
)
type
Name
,
err
:=
pos
(
w
,
r
,
2
)
chart
Name
,
err
:=
pos
(
w
,
r
,
2
)
if
err
!=
nil
{
return
err
}
re
gistry
,
err
:=
c
.
Manager
.
GetRegistryForType
(
type
Name
)
re
pository
,
err
:=
c
.
Manager
.
GetRepoForChart
(
chart
Name
)
if
err
!=
nil
{
httputil
.
BadRequest
(
w
,
r
,
err
)
return
nil
}
util
.
LogHandlerExitWithJSON
(
handler
,
w
,
re
gist
ry
,
http
.
StatusOK
)
util
.
LogHandlerExitWithJSON
(
handler
,
w
,
re
posito
ry
,
http
.
StatusOK
)
return
nil
}
func
getMetadataFor
Type
HandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: get
type
metadata"
func
getMetadataFor
Chart
HandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: get
chart
metadata"
util
.
LogHandlerEntry
(
handler
,
r
)
type
Name
,
err
:=
pos
(
w
,
r
,
2
)
chart
Name
,
err
:=
pos
(
w
,
r
,
2
)
if
err
!=
nil
{
return
err
}
metadata
,
err
:=
c
.
Manager
.
GetMetadataFor
Type
(
type
Name
)
metadata
,
err
:=
c
.
Manager
.
GetMetadataFor
Chart
(
chart
Name
)
if
err
!=
nil
{
httputil
.
BadRequest
(
w
,
r
,
err
)
return
nil
...
...
@@ -436,29 +438,37 @@ func getMetadataForTypeHandlerFunc(w http.ResponseWriter, r *http.Request, c *ro
return
nil
}
// Putting Registry handlers here for now because deployments.go
// currently owns its own Manager backend and doesn't like to share.
func
listRegistriesHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: list registries"
func
getChartHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: get chart"
util
.
LogHandlerEntry
(
handler
,
r
)
registries
,
err
:=
c
.
Manager
.
ListRegistries
(
)
chartName
,
err
:=
pos
(
w
,
r
,
2
)
if
err
!=
nil
{
return
err
}
util
.
LogHandlerExitWithJSON
(
handler
,
w
,
registries
,
http
.
StatusOK
)
ch
,
err
:=
c
.
Manager
.
GetChart
(
chartName
)
if
err
!=
nil
{
httputil
.
BadRequest
(
w
,
r
,
err
)
return
nil
}
util
.
LogHandlerExitWithJSON
(
handler
,
w
,
ch
,
http
.
StatusOK
)
return
nil
}
func
getRegistryHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: get registry"
// TODO: Refactor this commented out code.
/*
func getRepoHandlerFunc(w http.ResponseWriter, r *http.Request, c *router.Context) error {
handler := "manager: get repository"
util.LogHandlerEntry(handler, r)
re
gistry
Name
,
err
:=
pos
(
w
,
r
,
2
)
re
po
Name, err := pos(w, r, 2)
if err != nil {
return err
}
cr
,
err
:=
c
.
Manager
.
GetRe
gistry
(
registry
Name
)
cr, err := c.Manager.GetRe
po(repo
Name)
if err != nil {
httputil.BadRequest(w, r, err)
return nil
...
...
@@ -468,10 +478,10 @@ func getRegistryHandlerFunc(w http.ResponseWriter, r *http.Request, c *router.Co
return nil
}
func
getRe
gistry
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
handler
string
)
*
common
.
Registry
{
func getRe
po(w http.ResponseWriter, r *http.Request, handler string) *repo.Repo
{
util.LogHandlerEntry(handler, r)
t
:=
&
common
.
Registry
{}
t := &
repo.Repo
{}
if err := httputil.Decode(w, r, t); err != nil {
httputil.BadRequest(w, r, err)
return nil
...
...
@@ -479,23 +489,23 @@ func getRegistry(w http.ResponseWriter, r *http.Request, handler string) *common
return t
}
func
createRe
gistry
HandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: create re
gist
ry"
func createRe
po
HandlerFunc(w http.ResponseWriter, r *http.Request, c *router.Context) error {
handler := "manager: create re
posito
ry"
util.LogHandlerEntry(handler, r)
defer r.Body.Close()
re
gistry
Name
,
err
:=
pos
(
w
,
r
,
2
)
re
po
Name, err := pos(w, r, 2)
if err != nil {
return err
}
reg
:=
getRe
gistry
(
w
,
r
,
handler
)
if
reg
.
Name
!=
re
gistry
Name
{
e
:=
fmt
.
Errorf
(
"Re
gistry name does not match %s != %s"
,
reg
.
Name
,
registry
Name
)
reg := getRe
po
(w, r, handler)
if reg.Name != re
po
Name {
e := fmt.Errorf("Re
po name does not match %s != %s", reg.Name, repo
Name)
httputil.BadRequest(w, r, e)
return nil
}
if reg != nil {
err
=
c
.
Manager
.
CreateRe
gistry
(
reg
)
err = c.Manager.CreateRe
po
(reg)
if err != nil {
httputil.BadRequest(w, r, err)
return nil
...
...
@@ -505,11 +515,12 @@ func createRegistryHandlerFunc(w http.ResponseWriter, r *http.Request, c *router
util.LogHandlerExitWithJSON(handler, w, reg, http.StatusOK)
return nil
}
*/
func
listRe
gistryType
sHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: list re
gistry type
s"
func
listRe
positoryChart
sHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: list re
pository chart
s"
util
.
LogHandlerEntry
(
handler
,
r
)
re
gistry
Name
,
err
:=
pos
(
w
,
r
,
2
)
re
po
Name
,
err
:=
pos
(
w
,
r
,
2
)
if
err
!=
nil
{
return
err
}
...
...
@@ -530,73 +541,40 @@ func listRegistryTypesHandlerFunc(w http.ResponseWriter, r *http.Request, c *rou
}
}
re
gistryTypes
,
err
:=
c
.
Manager
.
ListRegistryTypes
(
registry
Name
,
regex
)
re
poCharts
,
err
:=
c
.
Manager
.
ListRepoCharts
(
repo
Name
,
regex
)
if
err
!=
nil
{
return
err
}
util
.
LogHandlerExitWithJSON
(
handler
,
w
,
re
gistryType
s
,
http
.
StatusOK
)
util
.
LogHandlerExitWithJSON
(
handler
,
w
,
re
poChart
s
,
http
.
StatusOK
)
return
nil
}
func
get
DownloadURLs
HandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: get
download URL
s"
func
get
RepositoryChart
HandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: get
repository chart
s"
util
.
LogHandlerEntry
(
handler
,
r
)
registryName
,
err
:=
pos
(
w
,
r
,
2
)
if
err
!=
nil
{
return
err
}
typeName
,
err
:=
pos
(
w
,
r
,
4
)
repoName
,
err
:=
pos
(
w
,
r
,
2
)
if
err
!=
nil
{
return
err
}
tt
,
err
:=
registry
.
ParseType
(
typeName
)
chartName
,
err
:=
pos
(
w
,
r
,
4
)
if
err
!=
nil
{
return
err
}
cr
,
err
:=
c
.
Manager
.
GetDownloadURLs
(
registryName
,
tt
)
if
err
!=
nil
{
httputil
.
BadRequest
(
w
,
r
,
err
)
return
nil
}
urls
:=
[]
string
{}
for
_
,
u
:=
range
cr
{
urls
=
append
(
urls
,
u
.
String
())
}
util
.
LogHandlerExitWithJSON
(
handler
,
w
,
urls
,
http
.
StatusOK
)
return
nil
}
func
getFileHandlerFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
c
*
router
.
Context
)
error
{
handler
:=
"manager: get file"
util
.
LogHandlerEntry
(
handler
,
r
)
registryName
,
err
:=
pos
(
w
,
r
,
2
)
repoChart
,
err
:=
c
.
Manager
.
GetChartForRepo
(
repoName
,
chartName
)
if
err
!=
nil
{
return
err
}
file
:=
r
.
FormValue
(
"file"
)
if
file
==
""
{
return
err
}
b
,
err
:=
c
.
Manager
.
GetFile
(
registryName
,
file
)
if
err
!=
nil
{
httputil
.
BadRequest
(
w
,
r
,
err
)
return
nil
}
util
.
LogHandlerExitWithJSON
(
handler
,
w
,
b
,
http
.
StatusOK
)
util
.
LogHandlerExitWithJSON
(
handler
,
w
,
repoChart
,
http
.
StatusOK
)
return
nil
}
func
getCredential
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
handler
string
)
*
common
.
Registry
Credential
{
func
getCredential
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
handler
string
)
*
repo
.
Credential
{
util
.
LogHandlerEntry
(
handler
,
r
)
t
:=
&
common
.
Registry
Credential
{}
t
:=
&
repo
.
Credential
{}
if
err
:=
httputil
.
Decode
(
w
,
r
,
t
);
err
!=
nil
{
httputil
.
BadRequest
(
w
,
r
,
err
)
return
nil
...
...
cmd/manager/manager/expander.go
View file @
51bbfafc
...
...
@@ -43,8 +43,17 @@ type Expander interface {
ExpandTemplate
(
t
*
common
.
Template
)
(
*
ExpandedTemplate
,
error
)
}
// TODO: Remove mockResolver when type resolver is completely excised
type
mockResolver
struct
{
}
func
(
r
*
mockResolver
)
ResolveTypes
(
c
*
common
.
Configuration
,
i
[]
*
common
.
ImportFile
)
([]
*
common
.
ImportFile
,
error
)
{
return
nil
,
nil
}
// NewExpander returns a new initialized Expander.
func
NewExpander
(
url
string
,
tr
TypeResolver
)
Expander
{
func
NewExpander
(
url
string
)
Expander
{
tr
:=
&
mockResolver
{}
return
&
expander
{
url
,
tr
}
}
...
...
@@ -53,6 +62,12 @@ type expander struct {
typeResolver
TypeResolver
}
// TypeResolver finds Types in a Configuration which aren't yet reduceable to an import file
// or primitive, and attempts to replace them with a template from a URL.
type
TypeResolver
interface
{
ResolveTypes
(
config
*
common
.
Configuration
,
imports
[]
*
common
.
ImportFile
)
([]
*
common
.
ImportFile
,
error
)
}
func
(
e
*
expander
)
getBaseURL
()
string
{
return
fmt
.
Sprintf
(
"%s/expand"
,
e
.
expanderURL
)
}
...
...
cmd/manager/manager/expander_test.go
View file @
51bbfafc
...
...
@@ -32,21 +32,6 @@ import (
"github.com/ghodss/yaml"
)
type
mockResolver
struct
{
responses
[][]
*
common
.
ImportFile
t
*
testing
.
T
}
func
(
r
*
mockResolver
)
ResolveTypes
(
c
*
common
.
Configuration
,
i
[]
*
common
.
ImportFile
)
([]
*
common
.
ImportFile
,
error
)
{
if
len
(
r
.
responses
)
<
1
{
return
nil
,
nil
}
ret
:=
r
.
responses
[
0
]
r
.
responses
=
r
.
responses
[
1
:
]
return
ret
,
nil
}
var
validTemplateTestCaseData
=
common
.
Template
{
Name
:
"TestTemplate"
,
Content
:
string
(
validContentTestCaseData
),
...
...
@@ -232,7 +217,6 @@ type ExpanderTestCase struct {
Description
string
Error
string
Handler
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
Resolver
TypeResolver
ValidResponse
*
ExpandedTemplate
}
...
...
@@ -247,33 +231,21 @@ func TestExpandTemplate(t *testing.T) {
"expect success for ExpandTemplate"
,
""
,
expanderSuccessHandler
,
&
mockResolver
{},
getValidResponse
(
t
,
"expect success for ExpandTemplate"
),
},
{
"expect error for ExpandTemplate"
,
"cannot expand template"
,
expanderErrorHandler
,
&
mockResolver
{},
nil
,
},
{
"expect success for ExpandTemplate with two expansions"
,
""
,
roundTripHandler
,
&
mockResolver
{[][]
*
common
.
ImportFile
{
{},
{
&
common
.
ImportFile
{
Name
:
"test.py"
}},
},
t
},
roundTripResponse
,
},
}
for
_
,
etc
:=
range
tests
{
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
etc
.
Handler
))
defer
ts
.
Close
()
expander
:=
NewExpander
(
ts
.
URL
,
etc
.
Resolver
)
expander
:=
NewExpander
(
ts
.
URL
)
actualResponse
,
err
:=
expander
.
ExpandTemplate
(
&
validTemplateTestCaseData
)
if
err
!=
nil
{
message
:=
err
.
Error
()
...
...
cmd/manager/manager/manager.go
View file @
51bbfafc
...
...
@@ -19,15 +19,13 @@ package manager
import
(
"fmt"
"log"
"net/url"
"regexp"
"strings"
"time"
"github.com/kubernetes/helm/cmd/manager/repository"
"github.com/kubernetes/helm/pkg/chart"
"github.com/kubernetes/helm/pkg/common"
"github.com/kubernetes/helm/pkg/registry"
"github.com/kubernetes/helm/pkg/util"
"github.com/kubernetes/helm/pkg/repo"
)
// Manager manages a persistent set of Deployments.
...
...
@@ -44,26 +42,20 @@ type Manager interface {
GetManifest
(
deploymentName
string
,
manifest
string
)
(
*
common
.
Manifest
,
error
)
Expand
(
t
*
common
.
Template
)
(
*
common
.
Manifest
,
error
)
// Types
ListTypes
()
([]
string
,
error
)
ListInstances
(
typeName
string
)
([]
*
common
.
TypeInstance
,
error
)
GetRegistryForType
(
typeName
string
)
(
string
,
error
)
GetMetadataForType
(
typeName
string
)
(
string
,
error
)
// Charts
ListCharts
()
([]
string
,
error
)
ListChartInstances
(
chartName
string
)
([]
*
common
.
ChartInstance
,
error
)
GetRepoForChart
(
chartName
string
)
(
string
,
error
)
GetMetadataForChart
(
chartName
string
)
(
*
chart
.
Chartfile
,
error
)
GetChart
(
chartName
string
)
(
*
chart
.
Chart
,
error
)
// Registries
ListRegistries
()
([]
*
common
.
Registry
,
error
)
CreateRegistry
(
pr
*
common
.
Registry
)
error
GetRegistry
(
name
string
)
(
*
common
.
Registry
,
error
)
DeleteRegistry
(
name
string
)
error
// Registry Types
ListRegistryTypes
(
registryName
string
,
regex
*
regexp
.
Regexp
)
([]
registry
.
Type
,
error
)
GetDownloadURLs
(
registryName
string
,
t
registry
.
Type
)
([]
*
url
.
URL
,
error
)
GetFile
(
registryName
string
,
url
string
)
(
string
,
error
)
// Repo Charts
ListRepoCharts
(
repoName
string
,
regex
*
regexp
.
Regexp
)
([]
string
,
error
)
GetChartForRepo
(
repoName
,
chartName
string
)
(
*
chart
.
Chart
,
error
)
// Credentials
CreateCredential
(
name
string
,
c
*
common
.
Registry
Credential
)
error
GetCredential
(
name
string
)
(
*
common
.
Registry
Credential
,
error
)
CreateCredential
(
name
string
,
c
*
repo
.
Credential
)
error
GetCredential
(
name
string
)
(
*
repo
.
Credential
,
error
)
// Chart Repositories
ListChartRepos
()
([]
string
,
error
)
...
...
@@ -75,21 +67,20 @@ type manager struct {
expander
Expander
deployer
Deployer
repository
repository
.
Repository
re
gistryProvider
registry
.
Registry
Provider
service
common
.
Registry
Service
re
poProvider
repo
.
IRepo
Provider
service
repo
.
IRepo
Service
//TODO: add chart repo service
credentialProvider
common
.
CredentialProvider
credentialProvider
repo
.
I
CredentialProvider
}
// NewManager returns a new initialized Manager.
func
NewManager
(
expander
Expander
,
deployer
Deployer
,
repository
repository
.
Repository
,
registryProvider
registry
.
RegistryProvider
,
service
common
.
RegistryService
,
//TODO: add chart repo service
credentialProvider
common
.
CredentialProvider
)
Manager
{
return
&
manager
{
expander
,
deployer
,
repository
,
registryProvider
,
service
,
credentialProvider
}
repoProvider
repo
.
IRepoProvider
,
service
repo
.
IRepoService
,
credentialProvider
repo
.
ICredentialProvider
)
Manager
{
return
&
manager
{
expander
,
deployer
,
repository
,
repoProvider
,
service
,
credentialProvider
}
}
// ListDeployments returns the list of deployments
...
...
@@ -190,7 +181,7 @@ func (m *manager) CreateDeployment(t *common.Template) (*common.Deployment, erro
}
// Finally update the type instances for this deployment.
m
.
set
Type
Instances
(
t
.
Name
,
manifest
.
Name
,
manifest
.
Layout
)
m
.
set
Chart
Instances
(
t
.
Name
,
manifest
.
Name
,
manifest
.
Layout
)
return
m
.
repository
.
GetValidDeployment
(
t
.
Name
)
}
...
...
@@ -210,20 +201,20 @@ func (m *manager) createManifest(t *common.Template) (*common.Manifest, error) {
},
nil
}
func
(
m
*
manager
)
set
Type
Instances
(
deploymentName
string
,
manifestName
string
,
layout
*
common
.
Layout
)
{
m
.
repository
.
Clear
Type
InstancesForDeployment
(
deploymentName
)
func
(
m
*
manager
)
set
Chart
Instances
(
deploymentName
string
,
manifestName
string
,
layout
*
common
.
Layout
)
{
m
.
repository
.
Clear
Chart
InstancesForDeployment
(
deploymentName
)
instances
:=
make
(
map
[
string
][]
*
common
.
Type
Instance
)
instances
:=
make
(
map
[
string
][]
*
common
.
Chart
Instance
)
for
i
,
r
:=
range
layout
.
Resources
{
add
Type
Instances
(
&
instances
,
r
,
deploymentName
,
manifestName
,
fmt
.
Sprintf
(
"$.resources[%d]"
,
i
))
add
Chart
Instances
(
&
instances
,
r
,
deploymentName
,
manifestName
,
fmt
.
Sprintf
(
"$.resources[%d]"
,
i
))
}
m
.
repository
.
Add
Type
Instances
(
instances
)
m
.
repository
.
Add
Chart
Instances
(
instances
)
}
func
add
TypeInstances
(
instances
*
map
[
string
][]
*
common
.
Type
Instance
,
r
*
common
.
LayoutResource
,
deploymentName
string
,
manifestName
string
,
jsonPath
string
)
{
func
add
ChartInstances
(
instances
*
map
[
string
][]
*
common
.
Chart
Instance
,
r
*
common
.
LayoutResource
,
deploymentName
string
,
manifestName
string
,
jsonPath
string
)
{
// Add this resource.
inst
:=
&
common
.
Type
Instance
{
inst
:=
&
common
.
Chart
Instance
{
Name
:
r
.
Name
,
Type
:
r
.
Type
,
Deployment
:
deploymentName
,
...
...
@@ -235,7 +226,7 @@ func addTypeInstances(instances *map[string][]*common.TypeInstance, r *common.La
// Add all sub resources if they exist.
for
i
,
sr
:=
range
r
.
Resources
{
add
Type
Instances
(
instances
,
sr
,
deploymentName
,
manifestName
,
fmt
.
Sprintf
(
"%s.resources[%d]"
,
jsonPath
,
i
))
add
Chart
Instances
(
instances
,
sr
,
deploymentName
,
manifestName
,
fmt
.
Sprintf
(
"%s.resources[%d]"
,
jsonPath
,
i
))
}
}
...
...
@@ -286,7 +277,7 @@ func (m *manager) DeleteDeployment(name string, forget bool) (*common.Deployment
}
// Finally remove the type instances for this deployment.
m
.
repository
.
Clear
Type
InstancesForDeployment
(
name
)
m
.
repository
.
Clear
Chart
InstancesForDeployment
(
name
)
return
d
,
nil
}
...
...
@@ -319,7 +310,7 @@ func (m *manager) PutDeployment(name string, t *common.Template) (*common.Deploy
}
// Finally update the type instances for this deployment.
m
.
set
Type
Instances
(
t
.
Name
,
manifest
.
Name
,
manifest
.
Layout
)
m
.
set
Chart
Instances
(
t
.
Name
,
manifest
.
Name
,
manifest
.
Layout
)
return
m
.
repository
.
GetValidDeployment
(
t
.
Name
)
}
...
...
@@ -336,59 +327,47 @@ func (m *manager) Expand(t *common.Template) (*common.Manifest, error) {
},
nil
}
func
(
m
*
manager
)
List
Type
s
()
([]
string
,
error
)
{
return
m
.
repository
.
List
Type
s
()
func
(
m
*
manager
)
List
Chart
s
()
([]
string
,
error
)
{
return
m
.
repository
.
List
Chart
s
()
}
func
(
m
*
manager
)
List
Instances
(
typeName
string
)
([]
*
common
.
Type
Instance
,
error
)
{
return
m
.
repository
.
Get
TypeInstances
(
type
Name
)
func
(
m
*
manager
)
List
ChartInstances
(
chartName
string
)
([]
*
common
.
Chart
Instance
,
error
)
{
return
m
.
repository
.
Get
ChartInstances
(
chart
Name
)
}
// GetRe
gistryForType returns the registry where a type
resides.
func
(
m
*
manager
)
GetRe
gistryForType
(
type
Name
string
)
(
string
,
error
)
{
_
,
r
,
err
:=
registry
.
GetDownloadURLs
(
m
.
registryProvider
,
type
Name
)
// GetRe
poForChart returns the repository where a chart
resides.
func
(
m
*
manager
)
GetRe
poForChart
(
chart
Name
string
)
(
string
,
error
)
{
_
,
r
,
err
:=
m
.
repoProvider
.
GetChartByReference
(
chart
Name
)
if
err
!=
nil
{
return
""
,
err
}
return
r
.
Get
Registry
Name
(),
nil
return
r
.
GetName
(),
nil
}
// GetMetadataFor
Type returns the metadata for type
.
func
(
m
*
manager
)
GetMetadataFor
Type
(
typeName
string
)
(
string
,
error
)
{
URLs
,
r
,
err
:=
registry
.
GetDownloadURLs
(
m
.
registryProvider
,
type
Name
)
// GetMetadataFor
Chart returns the metadata for a chart
.
func
(
m
*
manager
)
GetMetadataFor
Chart
(
chartName
string
)
(
*
chart
.
Chartfile
,
error
)
{
c
,
_
,
err
:=
m
.
repoProvider
.
GetChartByReference
(
chart
Name
)
if
err
!=
nil
{
return
""
,
err
}
if
len
(
URLs
)
<
1
{
return
""
,
nil
return
nil
,
err
}
// If it's a chart, we want the provenance file
fPath
:=
URLs
[
0
]
if
!
strings
.
Contains
(
fPath
,
".prov"
)
{
// It's not a chart, so we want the schema
fPath
+=
".schema"
}
return
c
.
Chartfile
(),
nil
}
metadata
,
err
:=
getFileFromRegistry
(
fPath
,
r
)
// GetChart returns a chart.
func
(
m
*
manager
)
GetChart
(
chartName
string
)
(
*
chart
.
Chart
,
error
)
{
c
,
_
,
err
:=
m
.
repoProvider
.
GetChartByReference
(
chartName
)
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"cannot get metadata for type (%s): %s"
,
typeName
,
err
)
return
nil
,
err
}
return
metadata
,
nil
}
// ListRegistries returns the list of registries
func
(
m
*
manager
)
ListRegistries
()
([]
*
common
.
Registry
,
error
)
{
return
m
.
service
.
List
()
return
c
,
nil
}
// ListChartRepos returns the list of chart repositories
func
(
m
*
manager
)
ListChartRepos
()
([]
string
,
error
)
{
//TODO: implement
return
nil
,
nil
return
m
.
service
.
List
()
}
// AddChartRepo adds a chart repository to list of available chart repositories
...
...
@@ -399,22 +378,17 @@ func (m *manager) AddChartRepo(name string) error {
// RemoveChartRepo removes a chart repository to list of available chart repositories
func
(
m
*
manager
)
RemoveChartRepo
(
name
string
)
error
{
//TODO: implement
return
nil
return
m
.
service
.
Delete
(
name
)
}
func
(
m
*
manager
)
CreateRe
gistry
(
pr
*
common
.
Registry
)
error
{
func
(
m
*
manager
)
CreateRe
po
(
pr
repo
.
IRepo
)
error
{
return
m
.
service
.
Create
(
pr
)
}
func
(
m
*
manager
)
GetRe
gistry
(
name
string
)
(
*
common
.
Registry
,
error
)
{
func
(
m
*
manager
)
GetRe
po
(
name
string
)
(
repo
.
IRepo
,
error
)
{
return
m
.
service
.
Get
(
name
)
}
func
(
m
*
manager
)
DeleteRegistry
(
name
string
)
error
{
return
m
.
service
.
Delete
(
name
)
}
func
generateManifestName
()
string
{
return
fmt
.
Sprintf
(
"manifest-%d"
,
time
.
Now
()
.
UTC
()
.
UnixNano
())
}
...
...
@@ -437,54 +411,33 @@ func getResourceErrors(c *common.Configuration) []string {
return
errs
}
// ListRe
gistryTypes lists types in a given registry whose string valu
es
// conform to the supplied regular expression, or all
type
s, if the regular
// ListRe
poCharts lists charts in a given repository whose nam
es
// conform to the supplied regular expression, or all
chart
s, if the regular
// expression is nil.
func
(
m
*
manager
)
ListRe
gistryTypes
(
registryName
string
,
regex
*
regexp
.
Regexp
)
([]
registry
.
Type
,
error
)
{
r
,
err
:=
m
.
re
gistryProvider
.
GetRegistryByName
(
registry
Name
)
func
(
m
*
manager
)
ListRe
poCharts
(
repoName
string
,
regex
*
regexp
.
Regexp
)
([]
string
,
error
)
{
r
,
err
:=
m
.
re
poProvider
.
GetRepoByName
(
repo
Name
)
if
err
!=
nil
{
return
nil
,
err
}
return
r
.
List
Type
s
(
regex
)
return
r
.
List
Chart
s
(
regex
)
}
// GetDownloadURLs returns the URLs required to download the contents
// of a given type in a given registry.
func
(
m
*
manager
)
GetDownloadURLs
(
registryName
string
,
t
registry
.
Type
)
([]
*
url
.
URL
,
error
)
{
r
,
err
:=
m
.
registryProvider
.
GetRegistryByName
(
registryName
)
// GetChartForRepo returns a chart from a given repository.
func
(
m
*
manager
)
GetChartForRepo
(
repoName
,
chartName
string
)
(
*
chart
.
Chart
,
error
)
{
r
,
err
:=
m
.
repoProvider
.
GetRepoByName
(
repoName
)
if
err
!=
nil
{
return
nil
,
err
}
return
r
.
GetDownloadURLs
(
t
)
}
// GetFile returns a file from the backing registry
func
(
m
*
manager
)
GetFile
(
registryName
string
,
url
string
)
(
string
,
error
)
{
r
,
err
:=
m
.
registryProvider
.
GetRegistryByName
(
registryName
)
if
err
!=
nil
{
return
""
,
err
}
return
getFileFromRegistry
(
url
,
r
)
}
func
getFileFromRegistry
(
url
string
,
r
registry
.
Registry
)
(
string
,
error
)
{
getter
:=
util
.
NewHTTPClient
(
3
,
r
,
util
.
NewSleeper
())
body
,
_
,
err
:=
getter
.
Get
(
url
)
if
err
!=
nil
{
return
""
,
err
}
return
body
,
nil
return
r
.
GetChart
(
chartName
)
}
// CreateCredential creates a credential that can be used to authenticate to re
gist
ry
func
(
m
*
manager
)
CreateCredential
(
name
string
,
c
*
common
.
Registry
Credential
)
error
{
// CreateCredential creates a credential that can be used to authenticate to re
posito
ry
func
(
m
*
manager
)
CreateCredential
(
name
string
,
c
*
repo
.
Credential
)
error
{
return
m
.
credentialProvider
.
SetCredential
(
name
,
c
)
}
func
(
m
*
manager
)
GetCredential
(
name
string
)
(
*
common
.
Registry
Credential
,
error
)
{
func
(
m
*
manager
)
GetCredential
(
name
string
)
(
*
repo
.
Credential
,
error
)
{
return
m
.
credentialProvider
.
GetCredential
(
name
)
}
cmd/manager/manager/manager_test.go
View file @
51bbfafc
...
...
@@ -17,13 +17,13 @@ limitations under the License.
package
manager
import
(
"github.com/kubernetes/helm/pkg/common"
"github.com/kubernetes/helm/pkg/repo"
"errors"
"reflect"
"strings"
"testing"
"github.com/kubernetes/helm/pkg/common"
"github.com/kubernetes/helm/pkg/registry"
)
var
template
=
common
.
Template
{
Name
:
"test"
,
Content
:
"test"
}
...
...
@@ -134,9 +134,9 @@ type repositoryStub struct {
ManifestSet
map
[
string
]
*
common
.
Manifest
Deleted
[]
string
GetValid
[]
string
Type
Instances
map
[
string
][]
string
Type
InstancesCleared
bool
Get
Type
InstancesCalled
bool
Chart
Instances
map
[
string
][]
string
Chart
InstancesCleared
bool
Get
Chart
InstancesCalled
bool
ListTypesCalled
bool
DeploymentStates
[]
*
common
.
DeploymentState
}
...
...
@@ -148,9 +148,9 @@ func (repository *repositoryStub) reset() {
repository
.
ManifestSet
=
make
(
map
[
string
]
*
common
.
Manifest
)
repository
.
Deleted
=
make
([]
string
,
0
)
repository
.
GetValid
=
make
([]
string
,
0
)
repository
.
Type
Instances
=
make
(
map
[
string
][]
string
)
repository
.
Type
InstancesCleared
=
false
repository
.
Get
Type
InstancesCalled
=
false
repository
.
Chart
Instances
=
make
(
map
[
string
][]
string
)
repository
.
Chart
InstancesCleared
=
false
repository
.
Get
Chart
InstancesCalled
=
false
repository
.
ListTypesCalled
=
false
repository
.
DeploymentStates
=
[]
*
common
.
DeploymentState
{}
}
...
...
@@ -233,26 +233,26 @@ func (repository *repositoryStub) GetLatestManifest(d string) (*common.Manifest,
}
// Types.
func
(
repository
*
repositoryStub
)
List
Type
s
()
([]
string
,
error
)
{
func
(
repository
*
repositoryStub
)
List
Chart
s
()
([]
string
,
error
)
{
repository
.
ListTypesCalled
=
true
return
[]
string
{},
nil
}
func
(
repository
*
repositoryStub
)
Get
TypeInstances
(
t
string
)
([]
*
common
.
Type
Instance
,
error
)
{
repository
.
Get
Type
InstancesCalled
=
true
return
[]
*
common
.
Type
Instance
{},
nil
func
(
repository
*
repositoryStub
)
Get
ChartInstances
(
t
string
)
([]
*
common
.
Chart
Instance
,
error
)
{
repository
.
Get
Chart
InstancesCalled
=
true
return
[]
*
common
.
Chart
Instance
{},
nil
}
func
(
repository
*
repositoryStub
)
Clear
Type
InstancesForDeployment
(
d
string
)
error
{
repository
.
Type
InstancesCleared
=
true
func
(
repository
*
repositoryStub
)
Clear
Chart
InstancesForDeployment
(
d
string
)
error
{
repository
.
Chart
InstancesCleared
=
true
return
nil
}
func
(
repository
*
repositoryStub
)
Add
TypeInstances
(
is
map
[
string
][]
*
common
.
Type
Instance
)
error
{
func
(
repository
*
repositoryStub
)
Add
ChartInstances
(
is
map
[
string
][]
*
common
.
Chart
Instance
)
error
{
for
t
,
instances
:=
range
is
{
for
_
,
instance
:=
range
instances
{
d
:=
instance
.
Deployment
repository
.
TypeInstances
[
d
]
=
append
(
repository
.
Type
Instances
[
d
],
t
)
repository
.
ChartInstances
[
d
]
=
append
(
repository
.
Chart
Instances
[
d
],
t
)
}
}
...
...
@@ -264,10 +264,10 @@ func (repository *repositoryStub) Close() {}
var
testExpander
=
&
expanderStub
{}
var
testRepository
=
newRepositoryStub
()
var
testDeployer
=
newDeployerStub
()
var
testRe
gistryService
=
registry
.
NewInmemRegistry
Service
()
var
testCredentialProvider
=
re
gistry
.
NewInmemCredentialProvider
()
var
testProvider
=
re
gistry
.
NewRegistryProvider
(
nil
,
registry
.
NewTestGithubRegistryProvider
(
""
,
nil
),
registry
.
NewTestGCSRegistryProvider
(
""
,
nil
),
testCredentialProvider
)
var
testManager
=
NewManager
(
testExpander
,
testDeployer
,
testRepository
,
testProvider
,
testRe
gistry
Service
,
testCredentialProvider
)
var
testRe
poService
=
repo
.
NewInmemRepo
Service
()
var
testCredentialProvider
=
re
po
.
NewInmemCredentialProvider
()
var
testProvider
=
re
po
.
NewRepoProvider
(
nil
,
repo
.
NewGCSRepoProvider
(
testCredentialProvider
),
testCredentialProvider
)
var
testManager
=
NewManager
(
testExpander
,
testDeployer
,
testRepository
,
testProvider
,
testRe
po
Service
,
testCredentialProvider
)
func
TestListDeployments
(
t
*
testing
.
T
)
{
testRepository
.
reset
()
...
...
@@ -363,12 +363,12 @@ func TestCreateDeployment(t *testing.T) {
t
.
Fatal
(
"CreateDeployment success did not mark deployment as deployed"
)
}
if
!
testRepository
.
Type
InstancesCleared
{
if
!
testRepository
.
Chart
InstancesCleared
{
t
.
Fatal
(
"Repository did not clear type instances during creation"
)
}
if
!
reflect
.
DeepEqual
(
testRepository
.
Type
Instances
,
typeInstMap
)
{
t
.
Fatalf
(
"Unexpected type instances after CreateDeployment: %s"
,
testRepository
.
Type
Instances
)
if
!
reflect
.
DeepEqual
(
testRepository
.
Chart
Instances
,
typeInstMap
)
{
t
.
Fatalf
(
"Unexpected type instances after CreateDeployment: %s"
,
testRepository
.
Chart
Instances
)
}
}
...
...
@@ -397,7 +397,7 @@ func TestCreateDeploymentCreationFailure(t *testing.T) {
"Received: %v, %s. Expected: %s, %s."
,
d
,
err
,
"nil"
,
errTest
)
}
if
testRepository
.
Type
InstancesCleared
{
if
testRepository
.
Chart
InstancesCleared
{
t
.
Fatal
(
"Unexpected change to type instances during CreateDeployment failure."
)
}
}
...
...
@@ -437,7 +437,7 @@ func TestCreateDeploymentCreationResourceFailure(t *testing.T) {
"Received: %v, %v. Expected: %v, %v."
,
d
,
err
,
&
deployment
,
"nil"
)
}
if
!
testRepository
.
Type
InstancesCleared
{
if
!
testRepository
.
Chart
InstancesCleared
{
t
.
Fatal
(
"Repository did not clear type instances during creation"
)
}
}
...
...
@@ -486,7 +486,7 @@ func TestDeleteDeploymentForget(t *testing.T) {
}
}
if
!
testRepository
.
Type
InstancesCleared
{
if
!
testRepository
.
Chart
InstancesCleared
{
t
.
Fatal
(
"Expected type instances to be cleared during DeleteDeployment."
)
}
}
...
...
@@ -521,29 +521,29 @@ func TestExpand(t *testing.T) {
func
TestListTypes
(
t
*
testing
.
T
)
{
testRepository
.
reset
()
testManager
.
List
Type
s
()
testManager
.
List
Chart
s
()
if
!
testRepository
.
ListTypesCalled
{
t
.
Fatal
(
"expected repository List
Type
s() call."
)
t
.
Fatal
(
"expected repository List
Chart
s() call."
)
}
}
func
TestListInstances
(
t
*
testing
.
T
)
{
testRepository
.
reset
()
testManager
.
ListInstances
(
"all"
)
testManager
.
List
Chart
Instances
(
"all"
)
if
!
testRepository
.
Get
Type
InstancesCalled
{
t
.
Fatal
(
"expected repository Get
Type
Instances() call."
)
if
!
testRepository
.
Get
Chart
InstancesCalled
{
t
.
Fatal
(
"expected repository Get
Chart
Instances() call."
)
}
}
// TODO(jackgr): Implement TestListRe
gistryType
s
func
TestListRe
gistryType
s
(
t
*
testing
.
T
)
{
// TODO(jackgr): Implement TestListRe
poChart
s
func
TestListRe
poChart
s
(
t
*
testing
.
T
)
{
/*
types, err := testManager.ListRe
gistryType
s("", nil)
types, err := testManager.ListRe
poChart
s("", nil)
if err != nil {
t.Fatalf("cannot list re
gist
ry types: %s", err)
t.Fatalf("cannot list re
posito
ry types: %s", err)
}
*/
}
...
...
@@ -551,7 +551,7 @@ func TestListRegistryTypes(t *testing.T) {
// TODO(jackgr): Implement TestGetDownloadURLs
func
TestGetDownloadURLs
(
t
*
testing
.
T
)
{
/*
urls, err := testManager.GetDownloadURLs("", re
gistry
.Type{})
urls, err := testManager.GetDownloadURLs("", re
po
.Type{})
if err != nil {
t.Fatalf("cannot list get download urls: %s", err)
}
...
...
cmd/manager/manager/typeresolver.go
deleted
100644 → 0
View file @
91a007cf
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
manager
import
(
"fmt"
"net/http"
"github.com/kubernetes/helm/pkg/common"
"github.com/kubernetes/helm/pkg/registry"
"github.com/kubernetes/helm/pkg/util"
"github.com/ghodss/yaml"
)
const
(
maxURLImports
=
100
schemaSuffix
=
".schema"
)
// TypeResolver finds Types in a Configuration which aren't yet reduceable to an import file
// or primitive, and attempts to replace them with a template from a URL.
type
TypeResolver
interface
{
ResolveTypes
(
config
*
common
.
Configuration
,
imports
[]
*
common
.
ImportFile
)
([]
*
common
.
ImportFile
,
error
)
}
type
typeResolver
struct
{
maxUrls
int
rp
registry
.
RegistryProvider
c
util
.
HTTPClient
}
type
fetchableURL
struct
{
reg
registry
.
Registry
url
string
}
type
fetchUnit
struct
{
urls
[]
fetchableURL
}
// NewTypeResolver returns a new initialized TypeResolver.
func
NewTypeResolver
(
rp
registry
.
RegistryProvider
,
c
util
.
HTTPClient
)
TypeResolver
{
return
&
typeResolver
{
maxUrls
:
maxURLImports
,
rp
:
rp
,
c
:
c
}
}
func
resolverError
(
c
*
common
.
Configuration
,
err
error
)
error
{
return
fmt
.
Errorf
(
"cannot resolve types in configuration %s due to:
\n
%s
\n
"
,
c
,
err
)
}
func
(
tr
*
typeResolver
)
performHTTPGet
(
d
util
.
HTTPDoer
,
u
string
,
allowMissing
bool
)
(
content
string
,
err
error
)
{
g
:=
tr
.
c
if
d
!=
nil
{
g
=
util
.
NewHTTPClient
(
3
,
d
,
util
.
NewSleeper
())
}
r
,
code
,
err
:=
g
.
Get
(
u
)
if
err
!=
nil
{
return
""
,
err
}
if
allowMissing
&&
code
==
http
.
StatusNotFound
{
return
""
,
nil
}
if
code
!=
http
.
StatusOK
{
return
""
,
fmt
.
Errorf
(
"Received status code %d attempting to fetch Type at %s"
,
code
,
u
)
}
return
r
,
nil
}
// ResolveTypes resolves the types in the supplied configuration and returns
// resolved type definitions in t.ImportFiles. Types can be either
// primitive (i.e., built in), resolved (i.e., already t.ImportFiles), or remote
// (i.e., described by a URL that must be fetched to resolve the type).
func
(
tr
*
typeResolver
)
ResolveTypes
(
config
*
common
.
Configuration
,
imports
[]
*
common
.
ImportFile
)
([]
*
common
.
ImportFile
,
error
)
{
existing
:=
map
[
string
]
bool
{}
for
_
,
v
:=
range
imports
{
existing
[
v
.
Name
]
=
true
}
fetched
:=
map
[
string
][]
*
common
.
ImportFile
{}
// TODO(vaikas): Need to account for multiple URLs being fetched for a given type.
toFetch
:=
make
([]
*
fetchUnit
,
0
,
tr
.
maxUrls
)
for
_
,
r
:=
range
config
.
Resources
{
// Map the type to a fetchable URL (if applicable) or skip it if it's a non-fetchable type (primitive for example).
urls
,
urlRegistry
,
err
:=
registry
.
GetDownloadURLs
(
tr
.
rp
,
r
.
Type
)
if
err
!=
nil
{
return
nil
,
resolverError
(
config
,
fmt
.
Errorf
(
"Failed to understand download url for %s: %v"
,
r
.
Type
,
err
))
}
if
!
existing
[
r
.
Type
]
{
f
:=
&
fetchUnit
{}
for
_
,
u
:=
range
urls
{
if
len
(
u
)
>
0
{
f
.
urls
=
append
(
f
.
urls
,
fetchableURL
{
urlRegistry
,
u
})
// Add to existing map so it is not fetched multiple times.
existing
[
r
.
Type
]
=
true
}
}
if
len
(
f
.
urls
)
>
0
{
toFetch
=
append
(
toFetch
,
f
)
fetched
[
f
.
urls
[
0
]
.
url
]
=
append
(
fetched
[
f
.
urls
[
0
]
.
url
],
&
common
.
ImportFile
{
Name
:
r
.
Type
,
Path
:
f
.
urls
[
0
]
.
url
})
}
}
}
count
:=
0
for
len
(
toFetch
)
>
0
{
// 1. If short github URL, resolve to a download URL
// 2. Fetch import URL. Exit if no URLs left
// 3. Check/handle HTTP status
// 4. Store results in all ImportFiles from that URL
// 5. Check for the optional schema file at import URL + .schema
// 6. Repeat 2,3 for schema file
// 7. Add each schema import to fetch if not already done
// 8. Mark URL done. Return to 1.
if
count
>=
tr
.
maxUrls
{
return
nil
,
resolverError
(
config
,
fmt
.
Errorf
(
"Number of imports exceeds maximum of %d"
,
tr
.
maxUrls
))
}
templates
:=
[]
string
{}
url
:=
toFetch
[
0
]
.
urls
[
0
]
for
_
,
u
:=
range
toFetch
[
0
]
.
urls
{
template
,
err
:=
tr
.
performHTTPGet
(
u
.
reg
,
u
.
url
,
false
)
if
err
!=
nil
{
return
nil
,
resolverError
(
config
,
err
)
}
templates
=
append
(
templates
,
template
)
}
for
_
,
i
:=
range
fetched
[
url
.
url
]
{
template
,
err
:=
parseContent
(
templates
)
if
err
!=
nil
{
return
nil
,
resolverError
(
config
,
err
)
}
i
.
Content
=
template
}
schemaURL
:=
url
.
url
+
schemaSuffix
sch
,
err
:=
tr
.
performHTTPGet
(
url
.
reg
,
schemaURL
,
true
)
if
err
!=
nil
{
return
nil
,
resolverError
(
config
,
err
)
}
if
sch
!=
""
{
var
s
common
.
Schema
if
err
:=
yaml
.
Unmarshal
([]
byte
(
sch
),
&
s
);
err
!=
nil
{
return
nil
,
resolverError
(
config
,
err
)
}
// Here we handle any nested imports in the schema we've just fetched.
for
_
,
v
:=
range
s
.
Imports
{
i
:=
&
common
.
ImportFile
{
Name
:
v
.
Name
}
var
existingSchema
string
urls
,
urlRegistry
,
conversionErr
:=
registry
.
GetDownloadURLs
(
tr
.
rp
,
v
.
Path
)
if
conversionErr
!=
nil
{
return
nil
,
resolverError
(
config
,
fmt
.
Errorf
(
"Failed to understand download url for %s: %v"
,
v
.
Path
,
conversionErr
))
}
if
len
(
urls
)
==
0
{
// If it's not a fetchable URL, we need to use the type name as is, since it is a short name
// for a schema.
urls
=
[]
string
{
v
.
Path
}
}
for
_
,
u
:=
range
urls
{
if
len
(
fetched
[
u
])
==
0
{
// If this import URL is new to us, add it to the URLs to fetch.
toFetch
=
append
(
toFetch
,
&
fetchUnit
{[]
fetchableURL
{{
urlRegistry
,
u
}}})
}
else
{
// If this is not a new import URL and we've already fetched its contents,
// reuse them. Also, check if we also found a schema for that import URL and
// record those contents for re-use as well.
if
fetched
[
u
][
0
]
.
Content
!=
""
{
i
.
Content
=
fetched
[
u
][
0
]
.
Content
if
len
(
fetched
[
u
+
schemaSuffix
])
>
0
{
existingSchema
=
fetched
[
u
+
schemaSuffix
][
0
]
.
Content
}
}
}
fetched
[
u
]
=
append
(
fetched
[
u
],
i
)
if
existingSchema
!=
""
{
fetched
[
u
+
schemaSuffix
]
=
append
(
fetched
[
u
+
schemaSuffix
],
&
common
.
ImportFile
{
Name
:
v
.
Name
+
schemaSuffix
,
Content
:
existingSchema
})
}
}
}
// Add the schema we've fetched as the schema for any templates which used this URL.
for
_
,
i
:=
range
fetched
[
url
.
url
]
{
schemaImportName
:=
i
.
Name
+
schemaSuffix
fetched
[
schemaURL
]
=
append
(
fetched
[
schemaURL
],
&
common
.
ImportFile
{
Name
:
schemaImportName
,
Content
:
sch
})
}
}
count
=
count
+
1
toFetch
=
toFetch
[
1
:
]
}
ret
:=
[]
*
common
.
ImportFile
{}
for
_
,
v
:=
range
fetched
{
ret
=
append
(
ret
,
v
...
)
}
return
ret
,
nil
}
func
parseContent
(
templates
[]
string
)
(
string
,
error
)
{
if
len
(
templates
)
==
1
{
return
templates
[
0
],
nil
}
// If there are multiple URLs that need to be fetched, that implies it's a package
// of raw Kubernetes objects. We need to fetch them all as a unit and create a
// template representing a package out of that below.
fakeConfig
:=
&
common
.
Configuration
{}
for
_
,
template
:=
range
templates
{
o
,
err
:=
util
.
ParseKubernetesObject
([]
byte
(
template
))
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"not a kubernetes object: %+v"
,
template
)
}
// Looks like a native Kubernetes object, create a configuration out of it
fakeConfig
.
Resources
=
append
(
fakeConfig
.
Resources
,
o
)
}
marshalled
,
err
:=
yaml
.
Marshal
(
fakeConfig
)
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"Failed to marshal: %+v"
,
fakeConfig
)
}
return
string
(
marshalled
),
nil
}
cmd/manager/manager/typeresolver_test.go
deleted
100644 → 0
View file @
91a007cf
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
manager
import
(
"errors"
"net/http"
"reflect"
"strings"
"testing"
"github.com/ghodss/yaml"
"github.com/kubernetes/helm/pkg/common"
"github.com/kubernetes/helm/pkg/registry"
)
type
responseAndError
struct
{
err
error
code
int
resp
string
}
type
resolverTestCase
struct
{
config
string
imports
[]
*
common
.
ImportFile
responses
map
[
string
]
responseAndError
urlcount
int
expectedErr
error
importOut
[]
*
common
.
ImportFile
registryProvider
registry
.
RegistryProvider
}
type
testGetter
struct
{
responses
map
[
string
]
responseAndError
count
int
test
*
testing
.
T
}
var
count
=
0
func
(
tg
testGetter
)
Get
(
url
string
)
(
body
string
,
code
int
,
err
error
)
{
count
=
count
+
1
ret
:=
tg
.
responses
[
url
]
return
ret
.
resp
,
ret
.
code
,
ret
.
err
}
func
testDriver
(
c
resolverTestCase
,
t
*
testing
.
T
)
{
g
:=
&
testGetter
{
test
:
t
,
responses
:
c
.
responses
}
count
=
0
r
:=
&
typeResolver
{
maxUrls
:
5
,
rp
:
c
.
registryProvider
,
c
:
g
,
}
conf
:=
&
common
.
Configuration
{}
dataErr
:=
yaml
.
Unmarshal
([]
byte
(
c
.
config
),
conf
)
if
dataErr
!=
nil
{
panic
(
"bad test data"
)
}
result
,
err
:=
r
.
ResolveTypes
(
conf
,
c
.
imports
)
if
count
!=
c
.
urlcount
{
t
.
Errorf
(
"Expected %d url GETs but only %d found %#v"
,
c
.
urlcount
,
g
.
count
,
g
)
}
if
(
err
!=
nil
&&
c
.
expectedErr
==
nil
)
||
(
err
==
nil
&&
c
.
expectedErr
!=
nil
)
{
t
.
Errorf
(
"Expected error %s but found %s"
,
c
.
expectedErr
,
err
)
}
else
if
err
!=
nil
&&
!
strings
.
Contains
(
err
.
Error
(),
c
.
expectedErr
.
Error
())
{
t
.
Errorf
(
"Expected error %s but found %s"
,
c
.
expectedErr
,
err
)
}
resultImport
:=
map
[
common
.
ImportFile
]
bool
{}
expectedImport
:=
map
[
common
.
ImportFile
]
bool
{}
for
_
,
i
:=
range
result
{
resultImport
[
*
i
]
=
true
}
for
_
,
i
:=
range
c
.
importOut
{
expectedImport
[
*
i
]
=
true
}
if
!
reflect
.
DeepEqual
(
resultImport
,
expectedImport
)
{
t
.
Errorf
(
"Expected imports %+v but found %+v"
,
expectedImport
,
resultImport
)
}
}
var
simpleContent
=
`
resources:
- name: test
type: ReplicationController
`
func
TestNoImports
(
t
*
testing
.
T
)
{
test
:=
resolverTestCase
{
config
:
simpleContent
}
testDriver
(
test
,
t
)
}
var
includeImport
=
`
resources:
- name: foo
type: foo.py
`
func
TestIncludedImport
(
t
*
testing
.
T
)
{
imports
:=
[]
*
common
.
ImportFile
{{
Name
:
"foo.py"
}}
test
:=
resolverTestCase
{
config
:
includeImport
,
imports
:
imports
,
}
testDriver
(
test
,
t
)
}
var
templateSingleURL
=
`
resources:
- name: foo
type: http://my-fake-url
`
func
TestSingleUrl
(
t
*
testing
.
T
)
{
finalImports
:=
[]
*
common
.
ImportFile
{{
Name
:
"http://my-fake-url"
,
Path
:
"http://my-fake-url"
,
Content
:
"my-content"
}}
responses
:=
map
[
string
]
responseAndError
{
"http://my-fake-url"
:
{
nil
,
http
.
StatusOK
,
"my-content"
},
"http://my-fake-url.schema"
:
{
nil
,
http
.
StatusNotFound
,
""
},
}
test
:=
resolverTestCase
{
config
:
templateSingleURL
,
importOut
:
finalImports
,
urlcount
:
2
,
responses
:
responses
,
}
testDriver
(
test
,
t
)
}
func
TestSingleUrlWith500
(
t
*
testing
.
T
)
{
responses
:=
map
[
string
]
responseAndError
{
"http://my-fake-url"
:
{
nil
,
http
.
StatusInternalServerError
,
"my-content"
},
}
test
:=
resolverTestCase
{
config
:
templateSingleURL
,
urlcount
:
1
,
responses
:
responses
,
expectedErr
:
errors
.
New
(
"Received status code 500"
),
}
testDriver
(
test
,
t
)
}
var
schema1
=
`
imports:
- path: my-next-url
name: schema-import
`
func
TestSingleUrlWithSchema
(
t
*
testing
.
T
)
{
finalImports
:=
[]
*
common
.
ImportFile
{
{
Name
:
"http://my-fake-url"
,
Path
:
"http://my-fake-url"
,
Content
:
"my-content"
},
{
Name
:
"schema-import"
,
Content
:
"schema-import"
},
{
Name
:
"http://my-fake-url.schema"
,
Content
:
schema1
},
}
responses
:=
map
[
string
]
responseAndError
{
"http://my-fake-url"
:
{
nil
,
http
.
StatusOK
,
"my-content"
},
"http://my-fake-url.schema"
:
{
nil
,
http
.
StatusOK
,
schema1
},
"my-next-url"
:
{
nil
,
http
.
StatusOK
,
"schema-import"
},
"my-next-url.schema"
:
{
nil
,
http
.
StatusNotFound
,
""
},
}
test
:=
resolverTestCase
{
config
:
templateSingleURL
,
importOut
:
finalImports
,
urlcount
:
4
,
responses
:
responses
,
}
testDriver
(
test
,
t
)
}
var
templateExceedsMax
=
`
resources:
- name: foo
type: http://my-fake-url
- name: foo1
type: http://my-fake-url1
- name: foo2
type: http://my-fake-url2
- name: foo3
type: http://my-fake-url3
- name: foo4
type: http://my-fake-url4
- name: foo5
type: http://my-fake-url5
`
func
TestTooManyImports
(
t
*
testing
.
T
)
{
responses
:=
map
[
string
]
responseAndError
{
"http://my-fake-url"
:
{
nil
,
http
.
StatusOK
,
"my-content"
},
"http://my-fake-url.schema"
:
{
nil
,
http
.
StatusNotFound
,
""
},
"http://my-fake-url1"
:
{
nil
,
http
.
StatusOK
,
"my-content"
},
"http://my-fake-url1.schema"
:
{
nil
,
http
.
StatusNotFound
,
""
},
"http://my-fake-url2"
:
{
nil
,
http
.
StatusOK
,
"my-content"
},
"http://my-fake-url2.schema"
:
{
nil
,
http
.
StatusNotFound
,
""
},
"http://my-fake-url3"
:
{
nil
,
http
.
StatusOK
,
"my-content"
},
"http://my-fake-url3.schema"
:
{
nil
,
http
.
StatusNotFound
,
""
},
"http://my-fake-url4"
:
{
nil
,
http
.
StatusOK
,
"my-content"
},
"http://my-fake-url4.schema"
:
{
nil
,
http
.
StatusNotFound
,
""
},
"http://my-fake-url5"
:
{
nil
,
http
.
StatusOK
,
"my-content"
},
"http://my-fake-url5.schema"
:
{
nil
,
http
.
StatusNotFound
,
""
},
}
test
:=
resolverTestCase
{
config
:
templateExceedsMax
,
urlcount
:
10
,
responses
:
responses
,
expectedErr
:
errors
.
New
(
"Number of imports exceeds maximum of 5"
),
}
testDriver
(
test
,
t
)
}
var
templateSharesImport
=
`
resources:
- name: foo
type: http://my-fake-url
- name: foo1
type: http://my-fake-url1
`
var
schema2
=
`
imports:
- path: my-next-url
name: schema-import-1
`
func
TestSharedImport
(
t
*
testing
.
T
)
{
finalImports
:=
[]
*
common
.
ImportFile
{
{
Name
:
"http://my-fake-url"
,
Path
:
"http://my-fake-url"
,
Content
:
"my-content"
},
{
Name
:
"http://my-fake-url1"
,
Path
:
"http://my-fake-url1"
,
Content
:
"my-content-1"
},
{
Name
:
"schema-import"
,
Content
:
"schema-import"
},
{
Name
:
"schema-import-1"
,
Content
:
"schema-import"
},
{
Name
:
"http://my-fake-url.schema"
,
Content
:
schema1
},
{
Name
:
"http://my-fake-url1.schema"
,
Content
:
schema2
},
}
responses
:=
map
[
string
]
responseAndError
{
"http://my-fake-url"
:
{
nil
,
http
.
StatusOK
,
"my-content"
},
"http://my-fake-url.schema"
:
{
nil
,
http
.
StatusOK
,
schema1
},
"http://my-fake-url1"
:
{
nil
,
http
.
StatusOK
,
"my-content-1"
},
"http://my-fake-url1.schema"
:
{
nil
,
http
.
StatusOK
,
schema2
},
"my-next-url"
:
{
nil
,
http
.
StatusOK
,
"schema-import"
},
"my-next-url.schema"
:
{
nil
,
http
.
StatusNotFound
,
""
},
}
test
:=
resolverTestCase
{
config
:
templateSharesImport
,
urlcount
:
6
,
responses
:
responses
,
importOut
:
finalImports
,
}
testDriver
(
test
,
t
)
}
var
templateShortGithubTemplate
=
`
resources:
- name: foo
type: github.com/kubernetes/application-dm-templates/common/replicatedservice:v1
- name: foo1
type: github.com/kubernetes/application-dm-templates/common/replicatedservice:v2
`
func
TestShortGithubUrl
(
t
*
testing
.
T
)
{
finalImports
:=
[]
*
common
.
ImportFile
{
{
Name
:
"github.com/kubernetes/application-dm-templates/common/replicatedservice:v1"
,
Path
:
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
,
Content
:
"my-content"
},
{
Name
:
"github.com/kubernetes/application-dm-templates/common/replicatedservice:v2"
,
Path
:
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py"
,
Content
:
"my-content-2"
},
}
downloadResponses
:=
map
[
string
]
registry
.
DownloadResponse
{
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
:
{
Err
:
nil
,
Code
:
http
.
StatusOK
,
Body
:
"my-content"
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py.schema"
:
{
Err
:
nil
,
Code
:
http
.
StatusNotFound
,
Body
:
""
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py"
:
{
Err
:
nil
,
Code
:
http
.
StatusOK
,
Body
:
"my-content-2"
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py.schema"
:
{
Err
:
nil
,
Code
:
http
.
StatusNotFound
,
Body
:
""
},
}
githubURLMaps
:=
map
[
registry
.
Type
]
registry
.
TestURLAndError
{
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v1"
)
:
{
URL
:
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
,
Err
:
nil
},
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v2"
)
:
{
URL
:
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py"
,
Err
:
nil
},
}
gcsURLMaps
:=
map
[
registry
.
Type
]
registry
.
TestURLAndError
{
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v1"
)
:
{
URL
:
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
,
Err
:
nil
},
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v2"
)
:
{
URL
:
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py"
,
Err
:
nil
},
}
grp
:=
registry
.
NewTestGithubRegistryProviderWithDownloads
(
"github.com/kubernetes/application-dm-templates"
,
githubURLMaps
,
downloadResponses
)
gcsrp
:=
registry
.
NewTestGCSRegistryProvider
(
"gs://charts"
,
gcsURLMaps
)
test
:=
resolverTestCase
{
config
:
templateShortGithubTemplate
,
importOut
:
finalImports
,
urlcount
:
0
,
responses
:
map
[
string
]
responseAndError
{},
registryProvider
:
registry
.
NewRegistryProvider
(
nil
,
grp
,
gcsrp
,
registry
.
NewInmemCredentialProvider
()),
}
testDriver
(
test
,
t
)
}
cmd/manager/repository/persistent/persistent.go
View file @
51bbfafc
...
...
@@ -44,7 +44,7 @@ type pManifest struct {
type
pInstance
struct
{
ID
string
`bson:"_id"`
common
.
Type
Instance
common
.
Chart
Instance
}
type
pRepository
struct
{
...
...
@@ -428,8 +428,8 @@ func (r *pRepository) removeManifestsForDeployment(d *common.Deployment) error {
return
nil
}
// List
Type
s returns all types known from existing instances.
func
(
r
*
pRepository
)
List
Type
s
()
([]
string
,
error
)
{
// List
Chart
s returns all types known from existing instances.
func
(
r
*
pRepository
)
List
Chart
s
()
([]
string
,
error
)
{
var
result
[]
string
if
err
:=
r
.
Instances
.
Find
(
nil
)
.
Distinct
(
"typeinstance.type"
,
&
result
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot list type instances: %s"
,
err
)
...
...
@@ -438,9 +438,9 @@ func (r *pRepository) ListTypes() ([]string, error) {
return
result
,
nil
}
// Get
Type
Instances returns all instances of a given type. If typeName is empty
// Get
Chart
Instances returns all instances of a given type. If typeName is empty
// or equal to "all", returns all instances of all types.
func
(
r
*
pRepository
)
Get
TypeInstances
(
typeName
string
)
([]
*
common
.
Type
Instance
,
error
)
{
func
(
r
*
pRepository
)
Get
ChartInstances
(
typeName
string
)
([]
*
common
.
Chart
Instance
,
error
)
{
query
:=
bson
.
M
{
"typeinstance.type"
:
typeName
}
if
typeName
==
""
||
typeName
==
"all"
{
query
=
nil
...
...
@@ -451,17 +451,17 @@ func (r *pRepository) GetTypeInstances(typeName string) ([]*common.TypeInstance,
return
nil
,
fmt
.
Errorf
(
"cannot get instances of type %s: %s"
,
typeName
,
err
)
}
instances
:=
[]
*
common
.
Type
Instance
{}
instances
:=
[]
*
common
.
Chart
Instance
{}
for
_
,
pi
:=
range
result
{
instances
=
append
(
instances
,
&
pi
.
Type
Instance
)
instances
=
append
(
instances
,
&
pi
.
Chart
Instance
)
}
return
instances
,
nil
}
// Clear
Type
InstancesForDeployment deletes all type instances associated with the given
// Clear
Chart
InstancesForDeployment deletes all type instances associated with the given
// deployment from the repository.
func
(
r
*
pRepository
)
Clear
Type
InstancesForDeployment
(
deploymentName
string
)
error
{
func
(
r
*
pRepository
)
Clear
Chart
InstancesForDeployment
(
deploymentName
string
)
error
{
if
deploymentName
!=
""
{
query
:=
bson
.
M
{
"typeinstance.deployment"
:
deploymentName
}
if
_
,
err
:=
r
.
Instances
.
RemoveAll
(
query
);
err
!=
nil
{
...
...
@@ -472,12 +472,12 @@ func (r *pRepository) ClearTypeInstancesForDeployment(deploymentName string) err
return
nil
}
// Add
Type
Instances adds the supplied type instances to the repository.
func
(
r
*
pRepository
)
Add
TypeInstances
(
instances
map
[
string
][]
*
common
.
Type
Instance
)
error
{
// Add
Chart
Instances adds the supplied type instances to the repository.
func
(
r
*
pRepository
)
Add
ChartInstances
(
instances
map
[
string
][]
*
common
.
Chart
Instance
)
error
{
for
_
,
is
:=
range
instances
{
for
_
,
i
:=
range
is
{
key
:=
fmt
.
Sprintf
(
"%s.%s.%s"
,
i
.
Deployment
,
i
.
Type
,
i
.
Name
)
wrapper
:=
pInstance
{
ID
:
key
,
Type
Instance
:
*
i
}
wrapper
:=
pInstance
{
ID
:
key
,
Chart
Instance
:
*
i
}
if
err
:=
r
.
Instances
.
Insert
(
&
wrapper
);
err
!=
nil
{
return
fmt
.
Errorf
(
"cannot insert type instance %v: %s"
,
wrapper
,
err
)
}
...
...
cmd/manager/repository/persistent/persistent_test.go
View file @
51bbfafc
...
...
@@ -102,9 +102,9 @@ func TestRepositoryDeleteDeploymentWorksForget(t *testing.T) {
}
}
func
TestRepository
Type
Instances
(
t
*
testing
.
T
)
{
func
TestRepository
Chart
Instances
(
t
*
testing
.
T
)
{
if
r
:=
createRepository
();
r
!=
nil
{
defer
resetRepository
(
t
,
r
)
repository
.
TestRepository
Type
Instances
(
t
,
r
)
repository
.
TestRepository
Chart
Instances
(
t
,
r
)
}
}
cmd/manager/repository/repository.go
View file @
51bbfafc
...
...
@@ -40,10 +40,10 @@ type Repository interface {
GetLatestManifest
(
deploymentName
string
)
(
*
common
.
Manifest
,
error
)
// Types.
List
Type
s
()
([]
string
,
error
)
Get
TypeInstances
(
typeName
string
)
([]
*
common
.
Type
Instance
,
error
)
Clear
Type
InstancesForDeployment
(
deploymentName
string
)
error
Add
TypeInstances
(
instances
map
[
string
][]
*
common
.
Type
Instance
)
error
List
Chart
s
()
([]
string
,
error
)
Get
ChartInstances
(
chartName
string
)
([]
*
common
.
Chart
Instance
,
error
)
Clear
Chart
InstancesForDeployment
(
deploymentName
string
)
error
Add
ChartInstances
(
instances
map
[
string
][]
*
common
.
Chart
Instance
)
error
Close
()
}
cmd/manager/repository/test_common.go
View file @
51bbfafc
...
...
@@ -210,9 +210,9 @@ func TestRepositoryDeleteDeploymentWorksForget(t *testing.T, r Repository) {
}
}
// TestRepository
Type
Instances checks that type instances can be listed and retrieved successfully.
func
TestRepository
Type
Instances
(
t
*
testing
.
T
,
r
Repository
)
{
d1Map
:=
map
[
string
][]
*
common
.
Type
Instance
{
// TestRepository
Chart
Instances checks that type instances can be listed and retrieved successfully.
func
TestRepository
Chart
Instances
(
t
*
testing
.
T
,
r
Repository
)
{
d1Map
:=
map
[
string
][]
*
common
.
Chart
Instance
{
"t1"
:
{
{
Name
:
"i1"
,
...
...
@@ -224,7 +224,7 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
},
}
d2Map
:=
map
[
string
][]
*
common
.
Type
Instance
{
d2Map
:=
map
[
string
][]
*
common
.
Chart
Instance
{
"t2"
:
{
{
Name
:
"i2"
,
...
...
@@ -236,7 +236,7 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
},
}
d3Map
:=
map
[
string
][]
*
common
.
Type
Instance
{
d3Map
:=
map
[
string
][]
*
common
.
Chart
Instance
{
"t2"
:
{
{
Name
:
"i3"
,
...
...
@@ -248,7 +248,7 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
},
}
instances
,
err
:=
r
.
Get
Type
Instances
(
"noinstances"
)
instances
,
err
:=
r
.
Get
Chart
Instances
(
"noinstances"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -257,7 +257,7 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
t
.
Fatalf
(
"expected no instances: %v"
,
instances
)
}
types
,
err
:=
r
.
List
Type
s
()
types
,
err
:=
r
.
List
Chart
s
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -266,11 +266,11 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
t
.
Fatalf
(
"expected no types: %v"
,
types
)
}
r
.
Add
Type
Instances
(
d1Map
)
r
.
Add
Type
Instances
(
d2Map
)
r
.
Add
Type
Instances
(
d3Map
)
r
.
Add
Chart
Instances
(
d1Map
)
r
.
Add
Chart
Instances
(
d2Map
)
r
.
Add
Chart
Instances
(
d3Map
)
instances
,
err
=
r
.
Get
Type
Instances
(
"unknowntype"
)
instances
,
err
=
r
.
Get
Chart
Instances
(
"unknowntype"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -279,7 +279,7 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
t
.
Fatalf
(
"expected no instances: %v"
,
instances
)
}
instances
,
err
=
r
.
Get
Type
Instances
(
"t1"
)
instances
,
err
=
r
.
Get
Chart
Instances
(
"t1"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -288,7 +288,7 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
t
.
Fatalf
(
"expected one instance: %v"
,
instances
)
}
instances
,
err
=
r
.
Get
Type
Instances
(
"t2"
)
instances
,
err
=
r
.
Get
Chart
Instances
(
"t2"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -297,7 +297,7 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
t
.
Fatalf
(
"expected two instances: %v"
,
instances
)
}
instances
,
err
=
r
.
Get
Type
Instances
(
"all"
)
instances
,
err
=
r
.
Get
Chart
Instances
(
"all"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -306,7 +306,7 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
t
.
Fatalf
(
"expected three total instances: %v"
,
instances
)
}
types
,
err
=
r
.
List
Type
s
()
types
,
err
=
r
.
List
Chart
s
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -315,12 +315,12 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
t
.
Fatalf
(
"expected two total types: %v"
,
types
)
}
err
=
r
.
Clear
Type
InstancesForDeployment
(
"d1"
)
err
=
r
.
Clear
Chart
InstancesForDeployment
(
"d1"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
instances
,
err
=
r
.
Get
Type
Instances
(
"t1"
)
instances
,
err
=
r
.
Get
Chart
Instances
(
"t1"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -329,7 +329,7 @@ func TestRepositoryTypeInstances(t *testing.T, r Repository) {
t
.
Fatalf
(
"expected no instances after clear: %v"
,
instances
)
}
types
,
err
=
r
.
List
Type
s
()
types
,
err
=
r
.
List
Chart
s
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
cmd/manager/repository/transient/transient.go
View file @
51bbfafc
...
...
@@ -27,16 +27,16 @@ import (
"github.com/kubernetes/helm/pkg/common"
)
// deployment
Type
InstanceMap stores type instances mapped by deployment name.
// deployment
Chart
InstanceMap stores type instances mapped by deployment name.
// This allows for simple updating and deleting of per-deployment instances
// when deployments are created/updated/deleted.
type
deployment
TypeInstanceMap
map
[
string
][]
*
common
.
Type
Instance
type
deployment
ChartInstanceMap
map
[
string
][]
*
common
.
Chart
Instance
type
tRepository
struct
{
sync
.
RWMutex
deployments
map
[
string
]
common
.
Deployment
manifests
map
[
string
]
map
[
string
]
*
common
.
Manifest
instances
map
[
string
]
deployment
Type
InstanceMap
instances
map
[
string
]
deployment
Chart
InstanceMap
}
// NewRepository returns a new transient repository. Its lifetime is coupled
...
...
@@ -46,14 +46,14 @@ func NewRepository() repository.Repository {
return
&
tRepository
{
deployments
:
make
(
map
[
string
]
common
.
Deployment
,
0
),
manifests
:
make
(
map
[
string
]
map
[
string
]
*
common
.
Manifest
,
0
),
instances
:
make
(
map
[
string
]
deployment
Type
InstanceMap
,
0
),
instances
:
make
(
map
[
string
]
deployment
Chart
InstanceMap
,
0
),
}
}
func
(
r
*
tRepository
)
Close
()
{
r
.
deployments
=
make
(
map
[
string
]
common
.
Deployment
,
0
)
r
.
manifests
=
make
(
map
[
string
]
map
[
string
]
*
common
.
Manifest
,
0
)
r
.
instances
=
make
(
map
[
string
]
deployment
Type
InstanceMap
,
0
)
r
.
instances
=
make
(
map
[
string
]
deployment
Chart
InstanceMap
,
0
)
}
// ListDeployments returns of all of the deployments in the repository.
...
...
@@ -258,8 +258,8 @@ func (r *tRepository) GetLatestManifest(deploymentName string) (*common.Manifest
return
r
.
getManifestForDeployment
(
deploymentName
,
d
.
LatestManifest
)
}
// List
Type
s returns all types known from existing instances.
func
(
r
*
tRepository
)
List
Type
s
()
([]
string
,
error
)
{
// List
Chart
s returns all types known from existing instances.
func
(
r
*
tRepository
)
List
Chart
s
()
([]
string
,
error
)
{
var
keys
[]
string
for
k
:=
range
r
.
instances
{
keys
=
append
(
keys
,
k
)
...
...
@@ -268,10 +268,10 @@ func (r *tRepository) ListTypes() ([]string, error) {
return
keys
,
nil
}
// Get
Type
Instances returns all instances of a given type. If type is empty,
// Get
Chart
Instances returns all instances of a given type. If type is empty,
// returns all instances for all types.
func
(
r
*
tRepository
)
Get
TypeInstances
(
typeName
string
)
([]
*
common
.
Type
Instance
,
error
)
{
var
instances
[]
*
common
.
Type
Instance
func
(
r
*
tRepository
)
Get
ChartInstances
(
typeName
string
)
([]
*
common
.
Chart
Instance
,
error
)
{
var
instances
[]
*
common
.
Chart
Instance
for
t
,
dInstMap
:=
range
r
.
instances
{
if
t
==
typeName
||
typeName
==
""
||
typeName
==
"all"
{
for
_
,
i
:=
range
dInstMap
{
...
...
@@ -283,9 +283,9 @@ func (r *tRepository) GetTypeInstances(typeName string) ([]*common.TypeInstance,
return
instances
,
nil
}
// Clear
Type
InstancesForDeployment deletes all type instances associated with the given
// Clear
Chart
InstancesForDeployment deletes all type instances associated with the given
// deployment from the repository.
func
(
r
*
tRepository
)
Clear
Type
InstancesForDeployment
(
deploymentName
string
)
error
{
func
(
r
*
tRepository
)
Clear
Chart
InstancesForDeployment
(
deploymentName
string
)
error
{
r
.
Lock
()
defer
r
.
Unlock
()
...
...
@@ -299,22 +299,22 @@ func (r *tRepository) ClearTypeInstancesForDeployment(deploymentName string) err
return
nil
}
// Add
Type
Instances adds the supplied type instances to the repository.
func
(
r
*
tRepository
)
Add
TypeInstances
(
instances
map
[
string
][]
*
common
.
Type
Instance
)
error
{
// Add
Chart
Instances adds the supplied type instances to the repository.
func
(
r
*
tRepository
)
Add
ChartInstances
(
instances
map
[
string
][]
*
common
.
Chart
Instance
)
error
{
r
.
Lock
()
defer
r
.
Unlock
()
// Add instances to the appropriate type and deployment maps.
for
t
,
is
:=
range
instances
{
if
r
.
instances
[
t
]
==
nil
{
r
.
instances
[
t
]
=
make
(
deployment
Type
InstanceMap
)
r
.
instances
[
t
]
=
make
(
deployment
Chart
InstanceMap
)
}
tmap
:=
r
.
instances
[
t
]
for
_
,
instance
:=
range
is
{
deployment
:=
instance
.
Deployment
if
tmap
[
deployment
]
==
nil
{
tmap
[
deployment
]
=
make
([]
*
common
.
Type
Instance
,
0
)
tmap
[
deployment
]
=
make
([]
*
common
.
Chart
Instance
,
0
)
}
tmap
[
deployment
]
=
append
(
tmap
[
deployment
],
instance
)
...
...
cmd/manager/repository/transient/transient_test.go
View file @
51bbfafc
...
...
@@ -50,6 +50,6 @@ func TestRepositoryDeleteDeploymentWorksForget(t *testing.T) {
repository
.
TestRepositoryDeleteDeploymentWorksForget
(
t
,
NewRepository
())
}
func
TestRepository
Type
Instances
(
t
*
testing
.
T
)
{
repository
.
TestRepository
Type
Instances
(
t
,
NewRepository
())
func
TestRepository
Chart
Instances
(
t
*
testing
.
T
)
{
repository
.
TestRepository
Chart
Instances
(
t
,
NewRepository
())
}
cmd/manager/router/context.go
View file @
51bbfafc
...
...
@@ -2,8 +2,8 @@ package router
import
(
"github.com/kubernetes/helm/cmd/manager/manager"
"github.com/kubernetes/helm/pkg/common"
helmhttp
"github.com/kubernetes/helm/pkg/httputil"
"github.com/kubernetes/helm/pkg/repo"
)
// Config holds the global configuration parameters passed into the router.
...
...
@@ -47,5 +47,5 @@ type Context struct {
// Manager is a helm/manager/manager.Manager
Manager
manager
.
Manager
Encoder
helmhttp
.
Encoder
CredentialProvider
common
.
CredentialProvider
CredentialProvider
repo
.
I
CredentialProvider
}
cmd/manager/testutil.go
View file @
51bbfafc
...
...
@@ -2,13 +2,13 @@ package main
import
(
"net/http/httptest"
"net/url"
"regexp"
"github.com/kubernetes/helm/cmd/manager/router"
"github.com/kubernetes/helm/pkg/chart"
"github.com/kubernetes/helm/pkg/common"
"github.com/kubernetes/helm/pkg/httputil"
"github.com/kubernetes/helm/pkg/re
gistry
"
"github.com/kubernetes/helm/pkg/re
po
"
)
// httpHarness is a simple test server fixture.
...
...
@@ -26,13 +26,13 @@ func httpHarness(c *router.Context, route string, fn router.HandlerFunc) *httpte
// This creates a stub context with the following properties:
// - Config is initialized to empty values
// - Encoder is initialized to httputil.DefaultEncoder
// - CredentialProvider is initialized to re
gistry
.InmemCredentialProvider
// - CredentialProvider is initialized to re
po
.InmemCredentialProvider
// - Manager is initialized to mockManager.
func
stubContext
()
*
router
.
Context
{
return
&
router
.
Context
{
Config
:
&
router
.
Config
{},
Manager
:
&
mockManager
{},
CredentialProvider
:
re
gistry
.
NewInmemCredentialProvider
(),
CredentialProvider
:
re
po
.
NewInmemCredentialProvider
(),
Encoder
:
httputil
.
DefaultEncoder
,
}
}
...
...
@@ -71,20 +71,24 @@ func (m *mockManager) Expand(t *common.Template) (*common.Manifest, error) {
return
&
common
.
Manifest
{},
nil
}
func
(
m
*
mockManager
)
List
Type
s
()
([]
string
,
error
)
{
func
(
m
*
mockManager
)
List
Chart
s
()
([]
string
,
error
)
{
return
[]
string
{},
nil
}
func
(
m
*
mockManager
)
List
Instances
(
typeName
string
)
([]
*
common
.
Type
Instance
,
error
)
{
return
[]
*
common
.
Type
Instance
{},
nil
func
(
m
*
mockManager
)
List
ChartInstances
(
chartName
string
)
([]
*
common
.
Chart
Instance
,
error
)
{
return
[]
*
common
.
Chart
Instance
{},
nil
}
func
(
m
*
mockManager
)
GetRe
gistryForType
(
type
Name
string
)
(
string
,
error
)
{
func
(
m
*
mockManager
)
GetRe
poForChart
(
chart
Name
string
)
(
string
,
error
)
{
return
""
,
nil
}
func
(
m
*
mockManager
)
GetMetadataForType
(
typeName
string
)
(
string
,
error
)
{
return
""
,
nil
func
(
m
*
mockManager
)
GetMetadataForChart
(
chartName
string
)
(
*
chart
.
Chartfile
,
error
)
{
return
nil
,
nil
}
func
(
m
*
mockManager
)
GetChart
(
chartName
string
)
(
*
chart
.
Chart
,
error
)
{
return
nil
,
nil
}
func
(
m
*
mockManager
)
AddChartRepo
(
name
string
)
error
{
...
...
@@ -99,32 +103,31 @@ func (m *mockManager) RemoveChartRepo(name string) error {
return
nil
}
func
(
m
*
mockManager
)
ListRe
gistries
()
([]
*
common
.
Registry
,
error
)
{
return
[]
*
common
.
Registry
{},
nil
func
(
m
*
mockManager
)
ListRe
pos
()
([]
*
repo
.
Repo
,
error
)
{
return
[]
*
repo
.
Repo
{},
nil
}
func
(
m
*
mockManager
)
CreateRe
gistry
(
pr
*
common
.
Registry
)
error
{
func
(
m
*
mockManager
)
CreateRe
po
(
pr
*
repo
.
Repo
)
error
{
return
nil
}
func
(
m
*
mockManager
)
GetRe
gistry
(
name
string
)
(
*
common
.
Registry
,
error
)
{
return
&
common
.
Registry
{},
nil
func
(
m
*
mockManager
)
GetRe
po
(
name
string
)
(
*
repo
.
Repo
,
error
)
{
return
&
repo
.
Repo
{},
nil
}
func
(
m
*
mockManager
)
DeleteRe
gistry
(
name
string
)
error
{
func
(
m
*
mockManager
)
DeleteRe
po
(
name
string
)
error
{
return
nil
}
func
(
m
*
mockManager
)
ListRegistryTypes
(
registryName
string
,
regex
*
regexp
.
Regexp
)
([]
registry
.
Type
,
error
)
{
return
[]
registry
.
Type
{},
nil
}
func
(
m
*
mockManager
)
GetDownloadURLs
(
registryName
string
,
t
registry
.
Type
)
([]
*
url
.
URL
,
error
)
{
return
[]
*
url
.
URL
{},
nil
func
(
m
*
mockManager
)
ListRepoCharts
(
repoName
string
,
regex
*
regexp
.
Regexp
)
([]
string
,
error
)
{
return
[]
string
{},
nil
}
func
(
m
*
mockManager
)
GetFile
(
registryName
string
,
url
string
)
(
string
,
error
)
{
return
""
,
nil
func
(
m
*
mockManager
)
GetChartForRepo
(
repoName
,
chartName
string
)
(
*
chart
.
Chart
,
error
)
{
return
nil
,
nil
}
func
(
m
*
mockManager
)
CreateCredential
(
name
string
,
c
*
common
.
RegistryCredential
)
error
{
func
(
m
*
mockManager
)
CreateCredential
(
name
string
,
c
*
repo
.
Credential
)
error
{
return
nil
}
func
(
m
*
mockManager
)
GetCredential
(
name
string
)
(
*
common
.
Registry
Credential
,
error
)
{
return
&
common
.
Registry
Credential
{},
nil
func
(
m
*
mockManager
)
GetCredential
(
name
string
)
(
*
repo
.
Credential
,
error
)
{
return
&
repo
.
Credential
{},
nil
}
pkg/common/types.go
View file @
51bbfafc
...
...
@@ -170,9 +170,9 @@ type Resource struct {
State
*
ResourceState
`json:"state,omitempty"`
}
//
Type
Instance defines the metadata for an instantiation of a template type
//
Chart
Instance defines the metadata for an instantiation of a template type
// in a deployment.
type
Type
Instance
struct
{
type
Chart
Instance
struct
{
Name
string
`json:"name"`
// instance name
Type
string
`json:"type"`
// instance type
Deployment
string
`json:"deployment"`
// deployment name
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment