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
b2f527d3
Commit
b2f527d3
authored
Feb 05, 2016
by
Jack Greenfield
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #207 from michelleN/make-test
add test targets in makefiles to run local tests
parents
93be549d
92d8d4b5
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
68 additions
and
41 deletions
+68
-41
.travis.yml
.travis.yml
+1
-1
Makefile
Makefile
+2
-0
Makefile
expandybird/Makefile
+4
-6
include.mk
include.mk
+30
-0
Makefile
manager/Makefile
+5
-7
manager_test.go
manager/manager/manager_test.go
+3
-3
typeresolver_test.go
manager/manager/typeresolver_test.go
+8
-8
filebased_credential_provider_test.go
registry/filebased_credential_provider_test.go
+1
-1
inmem_credential_provider.go
registry/inmem_credential_provider.go
+1
-1
inmem_credential_provider_test.go
registry/inmem_credential_provider_test.go
+1
-1
registryprovider.go
registry/registryprovider.go
+4
-4
Makefile
resourcifier/Makefile
+6
-7
configurations.go
resourcifier/configurations.go
+2
-2
No files found.
.travis.yml
View file @
b2f527d3
...
@@ -9,4 +9,4 @@ install:
...
@@ -9,4 +9,4 @@ install:
-
sudo pip install -r expandybird/requirements.txt
-
sudo pip install -r expandybird/requirements.txt
script
:
script
:
-
make test
-
make
setup-gotools
test
Makefile
View file @
b2f527d3
...
@@ -12,6 +12,8 @@
...
@@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# See the License for the specific language governing permissions and
# limitations under the License.
# limitations under the License.
include
include.mk
SUBDIRS
:=
expandybird/. resourcifier/. manager/.
SUBDIRS
:=
expandybird/. resourcifier/. manager/.
TARGETS
:=
all build
test
push container clean
TARGETS
:=
all build
test
push container clean
...
...
expandybird/Makefile
View file @
b2f527d3
...
@@ -12,6 +12,8 @@
...
@@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# See the License for the specific language governing permissions and
# limitations under the License.
# limitations under the License.
include
../include.mk
.PHONY
:
all build test push container clean
.PHONY
:
all build test push container clean
DOCKER_REGISTRY
:=
gcr.io
DOCKER_REGISTRY
:=
gcr.io
...
@@ -21,12 +23,6 @@ TAG := latest
...
@@ -21,12 +23,6 @@ TAG := latest
DIR
:=
.
DIR
:=
.
info
:
@
echo
"Build tag:
${
TAG
}
"
@
echo
"Registry:
${
DOCKER_REGISTRY
}
"
@
echo
"Project:
${
PROJECT
}
"
@
echo
"Image:
${
IMAGE
}
"
push
:
container
push
:
container
ifeq
($(DOCKER_REGISTRY),gcr.io)
ifeq
($(DOCKER_REGISTRY),gcr.io)
gcloud docker push $(PREFIX)/$(IMAGE)
:
$(TAG)
gcloud docker push $(PREFIX)/$(IMAGE)
:
$(TAG)
...
@@ -47,3 +43,5 @@ clean:
...
@@ -47,3 +43,5 @@ clean:
-
docker rmi
$(PREFIX)
/
$(IMAGE)
:
$(TAG)
-
docker rmi
$(PREFIX)
/
$(IMAGE)
:
$(TAG)
rm
-f
expandybird
rm
-f
expandybird
.PHONY
:
test
test
:
lint vet test-unit
include.mk
0 → 100644
View file @
b2f527d3
.PHONY: info
info:
@echo "Build tag: ${TAG}"
@echo "Registry: ${DOCKER_REGISTRY}"
@echo "Project: ${PROJECT}"
@echo "Image: ${IMAGE}"
.PHONY: test-unit
test-unit:
@echo Running tests...
go test -v ./...
.PHONY: lint
lint:
@echo Running golint...
golint ./...
@echo -----------------
.PHONY: vet
vet:
@echo Running go vet...
go vet ./...
@echo -----------------
.PHONY: setup-gotools
setup-gotools:
@echo Installing golint
go get -u github.com/golang/lint/golint
@echo Installing vet
go get -u -v golang.org/x/tools/cmd/vet
manager/Makefile
View file @
b2f527d3
...
@@ -12,7 +12,9 @@
...
@@ -12,7 +12,9 @@
# See the License for the specific language governing permissions and
# See the License for the specific language governing permissions and
# limitations under the License.
# limitations under the License.
.PHONY
:
all build test push container clean .project
include
../include.mk
.PHONY
:
all build push container clean .project
DOCKER_REGISTRY
:=
gcr.io
DOCKER_REGISTRY
:=
gcr.io
PREFIX
:=
$(DOCKER_REGISTRY)
/
$(PROJECT)
PREFIX
:=
$(DOCKER_REGISTRY)
/
$(PROJECT)
...
@@ -22,12 +24,6 @@ TAG := latest
...
@@ -22,12 +24,6 @@ TAG := latest
ROOT_DIR
:=
$
(
abspath ./..
)
ROOT_DIR
:=
$
(
abspath ./..
)
DIR
=
$(ROOT_DIR)
DIR
=
$(ROOT_DIR)
info
:
@
echo
"Build tag:
${
TAG
}
"
@
echo
"Registry:
${
DOCKER_REGISTRY
}
"
@
echo
"Project:
${
PROJECT
}
"
@
echo
"Image:
${
IMAGE
}
"
push
:
container
push
:
container
ifeq
($(DOCKER_REGISTRY),gcr.io)
ifeq
($(DOCKER_REGISTRY),gcr.io)
gcloud docker push $(PREFIX)/$(IMAGE)
:
$(TAG)
gcloud docker push $(PREFIX)/$(IMAGE)
:
$(TAG)
...
@@ -41,3 +37,5 @@ container:
...
@@ -41,3 +37,5 @@ container:
clean
:
clean
:
-
docker rmi
$(PREFIX)
/
$(IMAGE)
:
$(TAG)
-
docker rmi
$(PREFIX)
/
$(IMAGE)
:
$(TAG)
.PHONY
:
test
test
:
lint vet test-unit
manager/manager/manager_test.go
View file @
b2f527d3
...
@@ -325,7 +325,7 @@ func TestCreateDeployment(t *testing.T) {
...
@@ -325,7 +325,7 @@ func TestCreateDeployment(t *testing.T) {
d
,
err
:=
testManager
.
CreateDeployment
(
&
template
)
d
,
err
:=
testManager
.
CreateDeployment
(
&
template
)
if
!
reflect
.
DeepEqual
(
d
,
&
deployment
)
||
err
!=
nil
{
if
!
reflect
.
DeepEqual
(
d
,
&
deployment
)
||
err
!=
nil
{
t
.
Fatalf
(
"Expected a different set of response values from invoking CreateDeployment."
+
t
.
Fatalf
(
"Expected a different set of response values from invoking CreateDeployment."
+
"Received: %
s, %s. Expected: %s
, %s."
,
d
,
err
,
&
deployment
,
"nil"
)
"Received: %
v, %s. Expected: %#v
, %s."
,
d
,
err
,
&
deployment
,
"nil"
)
}
}
if
testRepository
.
Created
[
0
]
!=
template
.
Name
{
if
testRepository
.
Created
[
0
]
!=
template
.
Name
{
...
@@ -383,7 +383,7 @@ func TestCreateDeploymentCreationFailure(t *testing.T) {
...
@@ -383,7 +383,7 @@ func TestCreateDeploymentCreationFailure(t *testing.T) {
if
err
!=
errTest
||
d
!=
nil
{
if
err
!=
errTest
||
d
!=
nil
{
t
.
Fatalf
(
"Expected a different set of response values from invoking CreateDeployment."
+
t
.
Fatalf
(
"Expected a different set of response values from invoking CreateDeployment."
+
"Received: %
s
, %s. Expected: %s, %s."
,
d
,
err
,
"nil"
,
errTest
)
"Received: %
v
, %s. Expected: %s, %s."
,
d
,
err
,
"nil"
,
errTest
)
}
}
if
testRepository
.
TypeInstancesCleared
{
if
testRepository
.
TypeInstancesCleared
{
...
@@ -437,7 +437,7 @@ func TestDeleteDeploymentForget(t *testing.T) {
...
@@ -437,7 +437,7 @@ func TestDeleteDeploymentForget(t *testing.T) {
d
,
err
:=
testManager
.
CreateDeployment
(
&
template
)
d
,
err
:=
testManager
.
CreateDeployment
(
&
template
)
if
!
reflect
.
DeepEqual
(
d
,
&
deployment
)
||
err
!=
nil
{
if
!
reflect
.
DeepEqual
(
d
,
&
deployment
)
||
err
!=
nil
{
t
.
Fatalf
(
"Expected a different set of response values from invoking CreateDeployment."
+
t
.
Fatalf
(
"Expected a different set of response values from invoking CreateDeployment."
+
"Received: %
s, %s. Expected: %s
, %s."
,
d
,
err
,
&
deployment
,
"nil"
)
"Received: %
v, %s. Expected: %#v
, %s."
,
d
,
err
,
&
deployment
,
"nil"
)
}
}
if
testRepository
.
Created
[
0
]
!=
template
.
Name
{
if
testRepository
.
Created
[
0
]
!=
template
.
Name
{
...
...
manager/manager/typeresolver_test.go
View file @
b2f527d3
...
@@ -298,20 +298,20 @@ func TestShortGithubUrl(t *testing.T) {
...
@@ -298,20 +298,20 @@ func TestShortGithubUrl(t *testing.T) {
}
}
downloadResponses
:=
map
[
string
]
registry
.
DownloadResponse
{
downloadResponses
:=
map
[
string
]
registry
.
DownloadResponse
{
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
:
registry
.
DownloadResponse
{
nil
,
http
.
StatusOK
,
"my-content"
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
:
registry
.
DownloadResponse
{
Err
:
nil
,
Code
:
http
.
StatusOK
,
Body
:
"my-content"
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py.schema"
:
registry
.
DownloadResponse
{
nil
,
http
.
StatusNotFound
,
""
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py.schema"
:
registry
.
DownloadResponse
{
Err
:
nil
,
Code
:
http
.
StatusNotFound
,
Body
:
""
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py"
:
registry
.
DownloadResponse
{
nil
,
http
.
StatusOK
,
"my-content-2"
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py"
:
registry
.
DownloadResponse
{
Err
:
nil
,
Code
:
http
.
StatusOK
,
Body
:
"my-content-2"
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py.schema"
:
registry
.
DownloadResponse
{
nil
,
http
.
StatusNotFound
,
""
},
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py.schema"
:
registry
.
DownloadResponse
{
Err
:
nil
,
Code
:
http
.
StatusNotFound
,
Body
:
""
},
}
}
githubUrlMaps
:=
map
[
registry
.
Type
]
registry
.
TestURLAndError
{
githubUrlMaps
:=
map
[
registry
.
Type
]
registry
.
TestURLAndError
{
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v1"
)
:
registry
.
TestURLAndError
{
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
,
nil
},
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v1"
)
:
registry
.
TestURLAndError
{
URL
:
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
,
Err
:
nil
},
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v2"
)
:
registry
.
TestURLAndError
{
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py"
,
nil
},
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v2"
)
:
registry
.
TestURLAndError
{
URL
:
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py"
,
Err
:
nil
},
}
}
gcsUrlMaps
:=
map
[
registry
.
Type
]
registry
.
TestURLAndError
{
gcsUrlMaps
:=
map
[
registry
.
Type
]
registry
.
TestURLAndError
{
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v1"
)
:
registry
.
TestURLAndError
{
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
,
nil
},
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v1"
)
:
registry
.
TestURLAndError
{
URL
:
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py"
,
Err
:
nil
},
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v2"
)
:
registry
.
TestURLAndError
{
"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py"
,
nil
},
registry
.
NewTypeOrDie
(
"common"
,
"replicatedservice"
,
"v2"
)
:
registry
.
TestURLAndError
{
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
)
grp
:=
registry
.
NewTestGithubRegistryProviderWithDownloads
(
"github.com/kubernetes/application-dm-templates"
,
githubUrlMaps
,
downloadResponses
)
...
...
registry/filebased_credential_provider_test.go
View file @
b2f527d3
...
@@ -55,6 +55,6 @@ func TestSetAndGetBasicAuthFilebased(t *testing.T) {
...
@@ -55,6 +55,6 @@ func TestSetAndGetBasicAuthFilebased(t *testing.T) {
}
}
tc
:=
&
testCase
{
"test2"
,
tc
:=
&
testCase
{
"test2"
,
&
common
.
RegistryCredential
{
&
common
.
RegistryCredential
{
BasicAuth
:
common
.
BasicAuthCredential
{
"user"
,
"password"
}},
nil
}
BasicAuth
:
common
.
BasicAuthCredential
{
Username
:
"user"
,
Password
:
"password"
}},
nil
}
testGetCredential
(
t
,
cp
,
tc
)
testGetCredential
(
t
,
cp
,
tc
)
}
}
registry/inmem_credential_provider.go
View file @
b2f527d3
...
@@ -38,6 +38,6 @@ func (fcp *InmemCredentialProvider) GetCredential(name string) (*common.Registry
...
@@ -38,6 +38,6 @@ func (fcp *InmemCredentialProvider) GetCredential(name string) (*common.Registry
}
}
func
(
fcp
*
InmemCredentialProvider
)
SetCredential
(
name
string
,
credential
*
common
.
RegistryCredential
)
error
{
func
(
fcp
*
InmemCredentialProvider
)
SetCredential
(
name
string
,
credential
*
common
.
RegistryCredential
)
error
{
fcp
.
credentials
[
name
]
=
&
common
.
RegistryCredential
{
credential
.
APIToken
,
credential
.
BasicAuth
,
credential
.
ServiceAccount
}
fcp
.
credentials
[
name
]
=
&
common
.
RegistryCredential
{
APIToken
:
credential
.
APIToken
,
BasicAuth
:
credential
.
BasicAuth
,
ServiceAccount
:
credential
.
ServiceAccount
}
return
nil
return
nil
}
}
registry/inmem_credential_provider_test.go
View file @
b2f527d3
...
@@ -68,6 +68,6 @@ func TestSetAndGetBasicAuth(t *testing.T) {
...
@@ -68,6 +68,6 @@ func TestSetAndGetBasicAuth(t *testing.T) {
cp
:=
NewInmemCredentialProvider
()
cp
:=
NewInmemCredentialProvider
()
tc
:=
&
testCase
{
"testcredential"
,
tc
:=
&
testCase
{
"testcredential"
,
&
common
.
RegistryCredential
{
&
common
.
RegistryCredential
{
BasicAuth
:
common
.
BasicAuthCredential
{
"user"
,
"pass"
}},
nil
}
BasicAuth
:
common
.
BasicAuthCredential
{
Username
:
"user"
,
Password
:
"pass"
}},
nil
}
verifySetAndGetCredential
(
t
,
cp
,
tc
)
verifySetAndGetCredential
(
t
,
cp
,
tc
)
}
}
registry/registryprovider.go
View file @
b2f527d3
...
@@ -74,7 +74,7 @@ func NewRegistryProvider(rs common.RegistryService, grp GithubRegistryProvider,
...
@@ -74,7 +74,7 @@ func NewRegistryProvider(rs common.RegistryService, grp GithubRegistryProvider,
return
rp
return
rp
}
}
func
(
rp
registryProvider
)
getRegistry
(
cr
common
.
Registry
)
(
Registry
,
error
)
{
func
(
rp
*
registryProvider
)
getRegistry
(
cr
common
.
Registry
)
(
Registry
,
error
)
{
switch
cr
.
Type
{
switch
cr
.
Type
{
case
common
.
GithubRegistryType
:
case
common
.
GithubRegistryType
:
return
rp
.
grp
.
GetGithubRegistry
(
cr
)
return
rp
.
grp
.
GetGithubRegistry
(
cr
)
...
@@ -86,7 +86,7 @@ func (rp registryProvider) getRegistry(cr common.Registry) (Registry, error) {
...
@@ -86,7 +86,7 @@ func (rp registryProvider) getRegistry(cr common.Registry) (Registry, error) {
}
}
}
}
func
(
rp
registryProvider
)
GetRegistryByShortURL
(
URL
string
)
(
Registry
,
error
)
{
func
(
rp
*
registryProvider
)
GetRegistryByShortURL
(
URL
string
)
(
Registry
,
error
)
{
rp
.
RLock
()
rp
.
RLock
()
defer
rp
.
RUnlock
()
defer
rp
.
RUnlock
()
...
@@ -111,7 +111,7 @@ func (rp registryProvider) GetRegistryByShortURL(URL string) (Registry, error) {
...
@@ -111,7 +111,7 @@ func (rp registryProvider) GetRegistryByShortURL(URL string) (Registry, error) {
// findRegistryByShortURL trims the scheme from both the supplied URL
// findRegistryByShortURL trims the scheme from both the supplied URL
// and the short URL returned by GetRegistryShortURL.
// and the short URL returned by GetRegistryShortURL.
func
(
rp
registryProvider
)
findRegistryByShortURL
(
URL
string
)
Registry
{
func
(
rp
*
registryProvider
)
findRegistryByShortURL
(
URL
string
)
Registry
{
trimmed
:=
util
.
TrimURLScheme
(
URL
)
trimmed
:=
util
.
TrimURLScheme
(
URL
)
for
_
,
r
:=
range
rp
.
registries
{
for
_
,
r
:=
range
rp
.
registries
{
if
strings
.
HasPrefix
(
trimmed
,
util
.
TrimURLScheme
(
r
.
GetRegistryShortURL
()))
{
if
strings
.
HasPrefix
(
trimmed
,
util
.
TrimURLScheme
(
r
.
GetRegistryShortURL
()))
{
...
@@ -122,7 +122,7 @@ func (rp registryProvider) findRegistryByShortURL(URL string) Registry {
...
@@ -122,7 +122,7 @@ func (rp registryProvider) findRegistryByShortURL(URL string) Registry {
return
nil
return
nil
}
}
func
(
rp
registryProvider
)
GetRegistryByName
(
registryName
string
)
(
Registry
,
error
)
{
func
(
rp
*
registryProvider
)
GetRegistryByName
(
registryName
string
)
(
Registry
,
error
)
{
rp
.
RLock
()
rp
.
RLock
()
defer
rp
.
RUnlock
()
defer
rp
.
RUnlock
()
...
...
resourcifier/Makefile
View file @
b2f527d3
...
@@ -14,7 +14,9 @@
...
@@ -14,7 +14,9 @@
# If you update this image please check the tag value before pushing.
# If you update this image please check the tag value before pushing.
.PHONY
:
all build test push container clean
include
../include.mk
.PHONY
:
all build push container clean
DOCKER_REGISTRY
:=
gcr.io
DOCKER_REGISTRY
:=
gcr.io
PREFIX
:=
$(DOCKER_REGISTRY)
/
$(PROJECT)
PREFIX
:=
$(DOCKER_REGISTRY)
/
$(PROJECT)
...
@@ -24,12 +26,6 @@ TAG := latest
...
@@ -24,12 +26,6 @@ TAG := latest
ROOT_DIR
:=
$
(
abspath ./..
)
ROOT_DIR
:=
$
(
abspath ./..
)
DIR
=
$(ROOT_DIR)
DIR
=
$(ROOT_DIR)
info
:
@
echo
"Build tag:
${
TAG
}
"
@
echo
"Registry:
${
DOCKER_REGISTRY
}
"
@
echo
"Project:
${
PROJECT
}
"
@
echo
"Image:
${
IMAGE
}
"
push
:
container
push
:
container
ifeq
($(DOCKER_REGISTRY),gcr.io)
ifeq
($(DOCKER_REGISTRY),gcr.io)
gcloud docker push $(PREFIX)/$(IMAGE)
:
$(TAG)
gcloud docker push $(PREFIX)/$(IMAGE)
:
$(TAG)
...
@@ -42,3 +38,6 @@ container:
...
@@ -42,3 +38,6 @@ container:
clean
:
clean
:
-
docker rmi
$(PREFIX)
/
$(IMAGE)
:
$(TAG)
-
docker rmi
$(PREFIX)
/
$(IMAGE)
:
$(TAG)
.PHONY
:
test
test
:
lint vet test-unit
resourcifier/configurations.go
View file @
b2f527d3
...
@@ -77,7 +77,7 @@ func listConfigurationsHandlerFunc(w http.ResponseWriter, r *http.Request) {
...
@@ -77,7 +77,7 @@ func listConfigurationsHandlerFunc(w http.ResponseWriter, r *http.Request) {
}
}
c
:=
&
common
.
Configuration
{
c
:=
&
common
.
Configuration
{
[]
*
common
.
Resource
{
Resources
:
[]
*
common
.
Resource
{
{
Type
:
rtype
},
{
Type
:
rtype
},
},
},
}
}
...
@@ -106,7 +106,7 @@ func getConfigurationHandlerFunc(w http.ResponseWriter, r *http.Request) {
...
@@ -106,7 +106,7 @@ func getConfigurationHandlerFunc(w http.ResponseWriter, r *http.Request) {
}
}
c
:=
&
common
.
Configuration
{
c
:=
&
common
.
Configuration
{
[]
*
common
.
Resource
{
Resources
:
[]
*
common
.
Resource
{
{
Name
:
rname
,
Type
:
rtype
},
{
Name
:
rname
,
Type
:
rtype
},
},
},
}
}
...
...
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