本文整理汇总了Golang中github.com/juju/juju/apiserver/provisioner.NewProvisionerAPI函数的典型用法代码示例。如果您正苦于以下问题:Golang NewProvisionerAPI函数的具体用法?Golang NewProvisionerAPI怎么用?Golang NewProvisionerAPI使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了NewProvisionerAPI函数的17个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。
示例1: TestProvisionerFailsWithNonMachineAgentNonManagerUser
func (s *withoutStateServerSuite) TestProvisionerFailsWithNonMachineAgentNonManagerUser(c *gc.C) {
anAuthorizer := s.authorizer
anAuthorizer.EnvironManager = true
// Works with an environment manager, which is not a machine agent.
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Assert(err, gc.IsNil)
c.Assert(aProvisioner, gc.NotNil)
// But fails with neither a machine agent or an environment manager.
anAuthorizer.EnvironManager = false
aProvisioner, err = provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Assert(err, gc.NotNil)
c.Assert(aProvisioner, gc.IsNil)
c.Assert(err, gc.ErrorMatches, "permission denied")
}
开发者ID:zhouqt,项目名称:juju,代码行数:15,代码来源:provisioner_test.go
示例2: TestProvisioningInfoPermissions
func (s *withoutStateServerSuite) TestProvisioningInfoPermissions(c *gc.C) {
// Login as a machine agent for machine 0.
anAuthorizer := s.authorizer
anAuthorizer.EnvironManager = false
anAuthorizer.Tag = s.machines[0].Tag()
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Assert(err, gc.IsNil)
c.Assert(aProvisioner, gc.NotNil)
args := params.Entities{Entities: []params.Entity{
{Tag: s.machines[0].Tag().String()},
{Tag: s.machines[0].Tag().String() + "-lxc-0"},
{Tag: "machine-42"},
{Tag: s.machines[1].Tag().String()},
{Tag: "service-bar"},
}}
// Only machine 0 and containers therein can be accessed.
results, err := aProvisioner.ProvisioningInfo(args)
c.Assert(results, gc.DeepEquals, params.ProvisioningInfoResults{
Results: []params.ProvisioningInfoResult{
{Result: ¶ms.ProvisioningInfo{
Series: "quantal",
Networks: []string{},
Jobs: []params.MachineJob{params.JobHostUnits},
}},
{Error: apiservertesting.NotFoundError("machine 0/lxc/0")},
{Error: apiservertesting.ErrUnauthorized},
{Error: apiservertesting.ErrUnauthorized},
{Error: apiservertesting.ErrUnauthorized},
},
})
}
开发者ID:zhouqt,项目名称:juju,代码行数:33,代码来源:provisioner_test.go
示例3: TestMachinesWithTransientErrorsPermission
func (s *withoutStateServerSuite) TestMachinesWithTransientErrorsPermission(c *gc.C) {
// Machines where there's permission issues are omitted.
anAuthorizer := s.authorizer
anAuthorizer.EnvironManager = false
anAuthorizer.Tag = names.NewMachineTag("1")
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources,
anAuthorizer)
err = s.machines[0].SetStatus(params.StatusStarted, "blah", nil)
c.Assert(err, gc.IsNil)
err = s.machines[1].SetStatus(params.StatusError, "transient error",
map[string]interface{}{"transient": true, "foo": "bar"})
c.Assert(err, gc.IsNil)
err = s.machines[2].SetStatus(params.StatusError, "error", map[string]interface{}{"transient": false})
c.Assert(err, gc.IsNil)
err = s.machines[3].SetStatus(params.StatusError, "error", nil)
c.Assert(err, gc.IsNil)
result, err := aProvisioner.MachinesWithTransientErrors()
c.Assert(err, gc.IsNil)
c.Assert(result, gc.DeepEquals, params.StatusResults{
Results: []params.StatusResult{
{Id: "1", Life: "alive", Status: "error", Info: "transient error",
Data: map[string]interface{}{"transient": true, "foo": "bar"}},
},
})
}
开发者ID:zhouqt,项目名称:juju,代码行数:26,代码来源:provisioner_test.go
示例4: TestDistributionGroupMachineAgentAuth
func (s *withoutStateServerSuite) TestDistributionGroupMachineAgentAuth(c *gc.C) {
anAuthorizer := s.authorizer
anAuthorizer.Tag = names.NewMachineTag("1")
anAuthorizer.EnvironManager = false
provisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Check(err, gc.IsNil)
args := params.Entities{Entities: []params.Entity{
{Tag: "machine-0"},
{Tag: "machine-1"},
{Tag: "machine-42"},
{Tag: "machine-0-lxc-99"},
{Tag: "machine-1-lxc-99"},
{Tag: "machine-1-lxc-99-lxc-100"},
}}
result, err := provisioner.DistributionGroup(args)
c.Assert(err, gc.IsNil)
c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{
Results: []params.DistributionGroupResult{
{Error: apiservertesting.ErrUnauthorized},
{Result: []instance.Id{}},
{Error: apiservertesting.ErrUnauthorized},
// only a machine agent for the container or its
// parent may access it.
{Error: apiservertesting.ErrUnauthorized},
{Error: apiservertesting.NotFoundError("machine 1/lxc/99")},
{Error: apiservertesting.ErrUnauthorized},
},
})
}
开发者ID:zhouqt,项目名称:juju,代码行数:29,代码来源:provisioner_test.go
示例5: TestWatchMachineErrorRetry
func (s *withoutStateServerSuite) TestWatchMachineErrorRetry(c *gc.C) {
s.PatchValue(&provisioner.ErrorRetryWaitDelay, 2*coretesting.ShortWait)
c.Assert(s.resources.Count(), gc.Equals, 0)
_, err := s.provisioner.WatchMachineErrorRetry()
c.Assert(err, gc.IsNil)
// Verify the resources were registered and stop them when done.
c.Assert(s.resources.Count(), gc.Equals, 1)
resource := s.resources.Get("1")
defer statetesting.AssertStop(c, resource)
// Check that the Watch has consumed the initial event ("returned"
// in the Watch call)
wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher))
wc.AssertNoChange()
// We should now get a time triggered change.
wc.AssertOneChange()
// Make sure WatchMachineErrorRetry fails with a machine agent login.
anAuthorizer := s.authorizer
anAuthorizer.Tag = names.NewMachineTag("1")
anAuthorizer.EnvironManager = false
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Assert(err, gc.IsNil)
result, err := aProvisioner.WatchMachineErrorRetry()
c.Assert(err, gc.ErrorMatches, "permission denied")
c.Assert(result, gc.DeepEquals, params.NotifyWatchResult{})
}
开发者ID:zhouqt,项目名称:juju,代码行数:31,代码来源:provisioner_test.go
示例6: TestWatchEnvironMachines
func (s *withoutStateServerSuite) TestWatchEnvironMachines(c *gc.C) {
c.Assert(s.resources.Count(), gc.Equals, 0)
got, err := s.provisioner.WatchEnvironMachines()
c.Assert(err, gc.IsNil)
want := params.StringsWatchResult{
StringsWatcherId: "1",
Changes: []string{"0", "1", "2", "3", "4"},
}
c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId)
c.Assert(got.Changes, jc.SameContents, want.Changes)
// Verify the resources were registered and stop them when done.
c.Assert(s.resources.Count(), gc.Equals, 1)
resource := s.resources.Get("1")
defer statetesting.AssertStop(c, resource)
// Check that the Watch has consumed the initial event ("returned"
// in the Watch call)
wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher))
wc.AssertNoChange()
// Make sure WatchEnvironMachines fails with a machine agent login.
anAuthorizer := s.authorizer
anAuthorizer.Tag = names.NewMachineTag("1")
anAuthorizer.EnvironManager = false
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Assert(err, gc.IsNil)
result, err := aProvisioner.WatchEnvironMachines()
c.Assert(err, gc.ErrorMatches, "permission denied")
c.Assert(result, gc.DeepEquals, params.StringsWatchResult{})
}
开发者ID:zhouqt,项目名称:juju,代码行数:33,代码来源:provisioner_test.go
示例7: TestSetSupportedContainersPermissions
func (s *withoutStateServerSuite) TestSetSupportedContainersPermissions(c *gc.C) {
// Login as a machine agent for machine 0.
anAuthorizer := s.authorizer
anAuthorizer.EnvironManager = false
anAuthorizer.Tag = s.machines[0].Tag()
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Assert(err, gc.IsNil)
c.Assert(aProvisioner, gc.NotNil)
args := params.MachineContainersParams{
Params: []params.MachineContainers{{
MachineTag: "machine-0",
ContainerTypes: []instance.ContainerType{instance.LXC},
}, {
MachineTag: "machine-1",
ContainerTypes: []instance.ContainerType{instance.LXC},
}, {
MachineTag: "machine-42",
ContainerTypes: []instance.ContainerType{instance.LXC},
},
},
}
// Only machine 0 can have it's containers updated.
results, err := aProvisioner.SetSupportedContainers(args)
c.Assert(results, gc.DeepEquals, params.ErrorResults{
Results: []params.ErrorResult{
{Error: nil},
{Error: apiservertesting.ErrUnauthorized},
{Error: apiservertesting.ErrUnauthorized},
},
})
}
开发者ID:zhouqt,项目名称:juju,代码行数:32,代码来源:provisioner_test.go
示例8: TestMetadataNotInStateButInDataSources
func (s *ImageMetadataSuite) TestMetadataNotInStateButInDataSources(c *gc.C) {
// ensure metadata in data sources and not in state
useTestImageData(c, testImagesData)
criteria := cloudimagemetadata.MetadataFilter{Stream: "daily"}
found, err := s.State.CloudImageMetadataStorage.FindMetadata(criteria)
c.Assert(errors.IsNotFound(err), jc.IsTrue)
c.Assert(found, gc.HasLen, 0)
api, err := provisioner.NewProvisionerAPI(s.State, s.resources, s.authorizer)
c.Assert(err, jc.ErrorIsNil)
result, err := api.ProvisioningInfo(s.getTestMachinesTags(c))
c.Assert(err, jc.ErrorIsNil)
expected := s.expectedDataSoureImageMetadata()
s.assertImageMetadataResults(c, result, expected...)
// Also make sure that these images metadata has been written to state for re-use
saved, err := s.State.CloudImageMetadataStorage.FindMetadata(criteria)
c.Assert(err, jc.ErrorIsNil)
stateExpected := s.convertCloudImageMetadata(expected[0])
if len(saved["default cloud images"]) == len(stateExpected) {
for i, image := range saved["default cloud images"] {
stateExpected[i].DateCreated = image.DateCreated
}
}
c.Assert(saved, gc.DeepEquals, map[string][]cloudimagemetadata.Metadata{
"default cloud images": stateExpected,
})
}
开发者ID:bac,项目名称:juju,代码行数:31,代码来源:imagemetadata_test.go
示例9: TestEnvironConfigNonManager
func (s *withoutStateServerSuite) TestEnvironConfigNonManager(c *gc.C) {
// Now test it with a non-environment manager and make sure
// the secret attributes are masked.
anAuthorizer := s.authorizer
anAuthorizer.Tag = names.NewMachineTag("1")
anAuthorizer.EnvironManager = false
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources,
anAuthorizer)
c.Assert(err, gc.IsNil)
s.AssertEnvironConfig(c, aProvisioner, commontesting.NoSecrets)
}
开发者ID:zhouqt,项目名称:juju,代码行数:11,代码来源:provisioner_test.go
示例10: TestMetadataNone
func (s *ImageMetadataSuite) TestMetadataNone(c *gc.C) {
api, err := provisioner.NewProvisionerAPI(s.State, s.resources, s.authorizer)
c.Assert(err, jc.ErrorIsNil)
result, err := api.ProvisioningInfo(s.getTestMachinesTags(c))
c.Assert(err, jc.ErrorIsNil)
expected := make([][]params.CloudImageMetadata, len(s.machines))
for i, _ := range result.Results {
expected[i] = nil
}
s.assertImageMetadataResults(c, result, expected...)
}
开发者ID:bac,项目名称:juju,代码行数:13,代码来源:imagemetadata_test.go
示例11: TestMachinesWithTransientErrorsPermission
func (s *withoutControllerSuite) TestMachinesWithTransientErrorsPermission(c *gc.C) {
// Machines where there's permission issues are omitted.
anAuthorizer := s.authorizer
anAuthorizer.EnvironManager = false
anAuthorizer.Tag = names.NewMachineTag("1")
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources,
anAuthorizer)
now := time.Now()
sInfo := status.StatusInfo{
Status: status.Started,
Message: "blah",
Since: &now,
}
err = s.machines[0].SetStatus(sInfo)
c.Assert(err, jc.ErrorIsNil)
sInfo = status.StatusInfo{
Status: status.Error,
Message: "transient error",
Data: map[string]interface{}{"transient": true, "foo": "bar"},
Since: &now,
}
err = s.machines[1].SetStatus(sInfo)
c.Assert(err, jc.ErrorIsNil)
sInfo = status.StatusInfo{
Status: status.Error,
Message: "error",
Data: map[string]interface{}{"transient": false},
Since: &now,
}
err = s.machines[2].SetStatus(sInfo)
c.Assert(err, jc.ErrorIsNil)
sInfo = status.StatusInfo{
Status: status.Error,
Message: "error",
Since: &now,
}
err = s.machines[3].SetStatus(sInfo)
c.Assert(err, jc.ErrorIsNil)
result, err := aProvisioner.MachinesWithTransientErrors()
c.Assert(err, jc.ErrorIsNil)
c.Assert(result, gc.DeepEquals, params.StatusResults{
Results: []params.StatusResult{
{Id: "1", Life: "alive", Status: "error", Info: "transient error",
Data: map[string]interface{}{"transient": true, "foo": "bar"}},
},
})
}
开发者ID:bac,项目名称:juju,代码行数:48,代码来源:provisioner_test.go
示例12: setUpTest
func (s *provisionerSuite) setUpTest(c *gc.C, withController bool) {
s.JujuConnSuite.ConfigAttrs = map[string]interface{}{
"image-stream": "daily",
}
s.JujuConnSuite.SetUpTest(c)
// We're testing with address allocation on by default. There are
// separate tests to check the behavior when the flag is not
// enabled.
s.SetFeatureFlags(feature.AddressAllocation)
// Reset previous machines (if any) and create 3 machines
// for the tests, plus an optional controller machine.
s.machines = nil
// Note that the specific machine ids allocated are assumed
// to be numerically consecutive from zero.
if withController {
s.machines = append(s.machines, testing.AddControllerMachine(c, s.State))
}
for i := 0; i < 5; i++ {
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
c.Check(err, jc.ErrorIsNil)
s.machines = append(s.machines, machine)
}
// Create a FakeAuthorizer so we can check permissions,
// set up assuming we logged in as the environment manager.
s.authorizer = apiservertesting.FakeAuthorizer{
EnvironManager: true,
}
// Create the resource registry separately to track invocations to
// Register, and to register the root for tools URLs.
s.resources = common.NewResources()
// Create a provisioner API for the machine.
provisionerAPI, err := provisioner.NewProvisionerAPI(
s.State,
s.resources,
s.authorizer,
)
c.Assert(err, jc.ErrorIsNil)
s.provisioner = provisionerAPI
}
开发者ID:makyo,项目名称:juju,代码行数:43,代码来源:provisioner_test.go
示例13: TestMetadataFromState
func (s *ImageMetadataSuite) TestMetadataFromState(c *gc.C) {
api, err := provisioner.NewProvisionerAPI(s.State, s.resources, s.authorizer)
c.Assert(err, jc.ErrorIsNil)
expected := s.expectedDataSoureImageMetadata()
// Write metadata to state.
metadata := s.convertCloudImageMetadata(expected[0])
for _, m := range metadata {
err := s.State.CloudImageMetadataStorage.SaveMetadata(
[]cloudimagemetadata.Metadata{m},
)
c.Assert(err, jc.ErrorIsNil)
}
result, err := api.ProvisioningInfo(s.getTestMachinesTags(c))
c.Assert(err, jc.ErrorIsNil)
s.assertImageMetadataResults(c, result, expected...)
}
开发者ID:bac,项目名称:juju,代码行数:20,代码来源:imagemetadata_test.go
示例14: TestProvisioningInfoPermissions
func (s *withoutControllerSuite) TestProvisioningInfoPermissions(c *gc.C) {
// Login as a machine agent for machine 0.
anAuthorizer := s.authorizer
anAuthorizer.EnvironManager = false
anAuthorizer.Tag = s.machines[0].Tag()
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Assert(err, jc.ErrorIsNil)
c.Assert(aProvisioner, gc.NotNil)
args := params.Entities{Entities: []params.Entity{
{Tag: s.machines[0].Tag().String()},
{Tag: s.machines[0].Tag().String() + "-lxd-0"},
{Tag: "machine-42"},
{Tag: s.machines[1].Tag().String()},
{Tag: "application-bar"},
}}
// Only machine 0 and containers therein can be accessed.
results, err := aProvisioner.ProvisioningInfo(args)
controllerCfg := coretesting.FakeControllerConfig()
// Dummy provider uses a random port, which is added to cfg used to create environment.
apiPort := dummy.ApiPort(s.Environ.Provider())
controllerCfg["api-port"] = apiPort
c.Assert(results, jc.DeepEquals, params.ProvisioningInfoResults{
Results: []params.ProvisioningInfoResult{
{Result: ¶ms.ProvisioningInfo{
ControllerConfig: controllerCfg,
Series: "quantal",
Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
Tags: map[string]string{
tags.JujuController: coretesting.ControllerTag.Id(),
tags.JujuModel: coretesting.ModelTag.Id(),
},
}},
{Error: apiservertesting.NotFoundError("machine 0/lxd/0")},
{Error: apiservertesting.ErrUnauthorized},
{Error: apiservertesting.ErrUnauthorized},
{Error: apiservertesting.ErrUnauthorized},
},
})
}
开发者ID:kat-co,项目名称:juju,代码行数:41,代码来源:provisioninginfo_test.go
示例15: setUpTest
func (s *provisionerSuite) setUpTest(c *gc.C, withStateServer bool) {
s.JujuConnSuite.SetUpTest(c)
// Reset previous machines (if any) and create 3 machines
// for the tests, plus an optional state server machine.
s.machines = nil
// Note that the specific machine ids allocated are assumed
// to be numerically consecutive from zero.
if withStateServer {
s.machines = append(s.machines, testing.AddStateServerMachine(c, s.State))
}
for i := 0; i < 5; i++ {
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
c.Check(err, gc.IsNil)
s.machines = append(s.machines, machine)
}
// Create a FakeAuthorizer so we can check permissions,
// set up assuming we logged in as the environment manager.
s.authorizer = apiservertesting.FakeAuthorizer{
EnvironManager: true,
}
// Create the resource registry separately to track invocations to
// Register, and to register the root for tools URLs.
s.resources = common.NewResources()
// Create a provisioner API for the machine.
provisionerAPI, err := provisioner.NewProvisionerAPI(
s.State,
s.resources,
s.authorizer,
)
c.Assert(err, gc.IsNil)
s.provisioner = provisionerAPI
}
开发者ID:zhouqt,项目名称:juju,代码行数:36,代码来源:provisioner_test.go
示例16: newCustomAPI
func (s *containerSuite) newCustomAPI(c *gc.C, hostInstId instance.Id, addContainer, provisionContainer bool) *state.Machine {
anAuthorizer := s.authorizer
anAuthorizer.EnvironManager = false
anAuthorizer.Tag = s.machines[0].Tag()
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Assert(err, jc.ErrorIsNil)
c.Assert(aProvisioner, gc.NotNil)
s.provAPI = aProvisioner
if hostInstId != "" {
err = s.machines[0].SetProvisioned(hostInstId, "fake_nonce", nil)
c.Assert(err, jc.ErrorIsNil)
}
if !addContainer {
return nil
}
container, err := s.State.AddMachineInsideMachine(
state.MachineTemplate{
Series: "quantal",
Jobs: []state.MachineJob{state.JobHostUnits},
},
s.machines[0].Id(),
instance.LXC,
)
c.Assert(err, jc.ErrorIsNil)
if provisionContainer {
password, err := utils.RandomPassword()
c.Assert(err, jc.ErrorIsNil)
err = container.SetPassword(password)
c.Assert(err, jc.ErrorIsNil)
err = container.SetProvisioned("foo", "fake_nonce", nil)
c.Assert(err, jc.ErrorIsNil)
}
return container
}
开发者ID:makyo,项目名称:juju,代码行数:36,代码来源:container_test.go
示例17: TestLifeAsMachineAgent
func (s *withoutStateServerSuite) TestLifeAsMachineAgent(c *gc.C) {
// NOTE: This and the next call serve to test the two
// different authorization schemes:
// 1. Machine agents can access their own machine and
// any container that has their own machine as parent;
// 2. Environment managers can access any machine without
// a parent.
// There's no need to repeat this test for each method,
// because the authorization logic is common.
// Login as a machine agent for machine 0.
anAuthorizer := s.authorizer
anAuthorizer.EnvironManager = false
anAuthorizer.Tag = s.machines[0].Tag()
aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
c.Assert(err, gc.IsNil)
c.Assert(aProvisioner, gc.NotNil)
// Make the machine dead before trying to add containers.
err = s.machines[0].EnsureDead()
c.Assert(err, gc.IsNil)
// Create some containers to work on.
template := state.MachineTemplate{
Series: "quantal",
Jobs: []state.MachineJob{state.JobHostUnits},
}
var containers []*state.Machine
for i := 0; i < 3; i++ {
container, err := s.State.AddMachineInsideMachine(template, s.machines[0].Id(), instance.LXC)
c.Check(err, gc.IsNil)
containers = append(containers, container)
}
// Make one container dead.
err = containers[1].EnsureDead()
c.Assert(err, gc.IsNil)
args := params.Entities{Entities: []params.Entity{
{Tag: s.machines[0].Tag().String()},
{Tag: s.machines[1].Tag().String()},
{Tag: containers[0].Tag().String()},
{Tag: containers[1].Tag().String()},
{Tag: containers[2].Tag().String()},
{Tag: "machine-42"},
{Tag: "unit-foo-0"},
{Tag: "service-bar"},
}}
result, err := aProvisioner.Life(args)
c.Assert(err, gc.IsNil)
c.Assert(result, gc.DeepEquals, params.LifeResults{
Results: []params.LifeResult{
{Life: "dead"},
{Error: apiservertesting.ErrUnauthorized},
{Life: "alive"},
{Life: "dead"},
{Life: "alive"},
{Error: apiservertesting.ErrUnauthorized},
{Error: apiservertesting.ErrUnauthorized},
{Error: apiservertesting.ErrUnauthorized},
},
})
}
开发者ID:zhouqt,项目名称:juju,代码行数:62,代码来源:provisioner_test.go
注:本文中的github.com/juju/juju/apiserver/provisioner.NewProvisionerAPI函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论