Go interface design for a cluster provisioner application












0












$begingroup$


I'm fairly new to Go and working on an application to create VMs in a some cloud provider. I'm trying to design interfaces and I'd love some reviews.



The application creates a cluster (group of VMs with some software installed). The cluster has two roles: master and worker. And in each role, you can have node groups (master can have only one node group and worker role can have N node groups). So a role provisions N groups and a group provisions M nodes, updating status objects after each step. Here's what I've come up with so far (I've removed method parameters to make it easy to read):



// Initialize is used to initialize objects during a cluster creation. Use this
// at the given level (Role, Group or Node) to initialize things like status
// objects specific to that level.
type Initializer interface {
// Initialize inits objects in a Cluster type.
Initialize() error
}

// StatusUpdater is used to update status of Group or Node at a given level.
type StatusUpdater interface {
// UpdateStatus updates the ClusterStatus object.
UpdateStatus() error
}

// Deleter deletes clusters, node groups and nodes.
type Deleter interface {
// RunPreDelete is used to run things before deletion of resources.
RunPreDelete() error
// Delete deletes a Role, Group or Node interface.
Delete()
// RunPostDelete is used to run things after deletion of resources.
RunPostDelete() error
}

// Upgrade upgrades clusters and node groups.
type Upgrader interface {
// Upgradeable is used to determine if the cluster is ready for an upgrade.
Upgradeable() bool
// PrepareForUpgrade is used to prepare a Group for upgrade, like setting status to upgrading
PrepareForUpgrade() bool
UpgradeStrategy
}

// UpgradeStategy defines strategies for upgrade. Default strategy is delete a node and create an
// "upgraded" node. The default strategy reduces workload capacity during upgrade. Additive strategy
// creates a new node and when it is ready, registers new node with the cluster and removes the old
// node. This gives additional workload capacity during upgrade.
type UpgradeStrategy interface {
// Upgrade upgrades a cluster or a group.
Upgrade() error
}

// Ensurer ensures a resource is created and present.
type Ensurer interface {
// Ensure ensures a resource.
Ensure() error
}

// Provisioner provisions a Role (master or worker) in the cluster. This is the top level provisioner for
// a K8S cluster.
type Provisioner interface {
Initializer
// Role returns role name of the provisioner.
Role() string
// ProvisionRole provisions a K8S cluster role.
ProvisionRole() error
StatusUpdater
Deleter
}

// GroupProvisoner provisions a Group (master group and one or more worker groups).
type GroupProvisoner interface {
Initializer
// ProvisionGroup provisions a Group.
ProvisionGroup() error
StatusUpdater
Deleter
}

// NodeProvisioner provisions an individual node using the cloud provider APIs.
type NodeProvisioner interface {
Initializer
Ensurer
StatusUpdater
Deleter
}

// Node implements NodeProvisioner interface
type Node struct{}

// Group implements GroupProvisioner interface
type Group struct {
NodeProvisioner NodeProvisioner
}

// Master implements Provisioner
type Master struct {
Role string
GroupProvisoner GroupProvisoner
Upgrader Upgrader
StatusUpdater StatusUpdater
}

func NewMaster() Provisioner {
// Inject dependencies and return a &Master
}


Does this look like a good design? Is it idiomatic Go? Any suggestions are greatly appreciated!










share|improve this question







New contributor




ragas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$

















    0












    $begingroup$


    I'm fairly new to Go and working on an application to create VMs in a some cloud provider. I'm trying to design interfaces and I'd love some reviews.



    The application creates a cluster (group of VMs with some software installed). The cluster has two roles: master and worker. And in each role, you can have node groups (master can have only one node group and worker role can have N node groups). So a role provisions N groups and a group provisions M nodes, updating status objects after each step. Here's what I've come up with so far (I've removed method parameters to make it easy to read):



    // Initialize is used to initialize objects during a cluster creation. Use this
    // at the given level (Role, Group or Node) to initialize things like status
    // objects specific to that level.
    type Initializer interface {
    // Initialize inits objects in a Cluster type.
    Initialize() error
    }

    // StatusUpdater is used to update status of Group or Node at a given level.
    type StatusUpdater interface {
    // UpdateStatus updates the ClusterStatus object.
    UpdateStatus() error
    }

    // Deleter deletes clusters, node groups and nodes.
    type Deleter interface {
    // RunPreDelete is used to run things before deletion of resources.
    RunPreDelete() error
    // Delete deletes a Role, Group or Node interface.
    Delete()
    // RunPostDelete is used to run things after deletion of resources.
    RunPostDelete() error
    }

    // Upgrade upgrades clusters and node groups.
    type Upgrader interface {
    // Upgradeable is used to determine if the cluster is ready for an upgrade.
    Upgradeable() bool
    // PrepareForUpgrade is used to prepare a Group for upgrade, like setting status to upgrading
    PrepareForUpgrade() bool
    UpgradeStrategy
    }

    // UpgradeStategy defines strategies for upgrade. Default strategy is delete a node and create an
    // "upgraded" node. The default strategy reduces workload capacity during upgrade. Additive strategy
    // creates a new node and when it is ready, registers new node with the cluster and removes the old
    // node. This gives additional workload capacity during upgrade.
    type UpgradeStrategy interface {
    // Upgrade upgrades a cluster or a group.
    Upgrade() error
    }

    // Ensurer ensures a resource is created and present.
    type Ensurer interface {
    // Ensure ensures a resource.
    Ensure() error
    }

    // Provisioner provisions a Role (master or worker) in the cluster. This is the top level provisioner for
    // a K8S cluster.
    type Provisioner interface {
    Initializer
    // Role returns role name of the provisioner.
    Role() string
    // ProvisionRole provisions a K8S cluster role.
    ProvisionRole() error
    StatusUpdater
    Deleter
    }

    // GroupProvisoner provisions a Group (master group and one or more worker groups).
    type GroupProvisoner interface {
    Initializer
    // ProvisionGroup provisions a Group.
    ProvisionGroup() error
    StatusUpdater
    Deleter
    }

    // NodeProvisioner provisions an individual node using the cloud provider APIs.
    type NodeProvisioner interface {
    Initializer
    Ensurer
    StatusUpdater
    Deleter
    }

    // Node implements NodeProvisioner interface
    type Node struct{}

    // Group implements GroupProvisioner interface
    type Group struct {
    NodeProvisioner NodeProvisioner
    }

    // Master implements Provisioner
    type Master struct {
    Role string
    GroupProvisoner GroupProvisoner
    Upgrader Upgrader
    StatusUpdater StatusUpdater
    }

    func NewMaster() Provisioner {
    // Inject dependencies and return a &Master
    }


    Does this look like a good design? Is it idiomatic Go? Any suggestions are greatly appreciated!










    share|improve this question







    New contributor




    ragas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$















      0












      0








      0





      $begingroup$


      I'm fairly new to Go and working on an application to create VMs in a some cloud provider. I'm trying to design interfaces and I'd love some reviews.



      The application creates a cluster (group of VMs with some software installed). The cluster has two roles: master and worker. And in each role, you can have node groups (master can have only one node group and worker role can have N node groups). So a role provisions N groups and a group provisions M nodes, updating status objects after each step. Here's what I've come up with so far (I've removed method parameters to make it easy to read):



      // Initialize is used to initialize objects during a cluster creation. Use this
      // at the given level (Role, Group or Node) to initialize things like status
      // objects specific to that level.
      type Initializer interface {
      // Initialize inits objects in a Cluster type.
      Initialize() error
      }

      // StatusUpdater is used to update status of Group or Node at a given level.
      type StatusUpdater interface {
      // UpdateStatus updates the ClusterStatus object.
      UpdateStatus() error
      }

      // Deleter deletes clusters, node groups and nodes.
      type Deleter interface {
      // RunPreDelete is used to run things before deletion of resources.
      RunPreDelete() error
      // Delete deletes a Role, Group or Node interface.
      Delete()
      // RunPostDelete is used to run things after deletion of resources.
      RunPostDelete() error
      }

      // Upgrade upgrades clusters and node groups.
      type Upgrader interface {
      // Upgradeable is used to determine if the cluster is ready for an upgrade.
      Upgradeable() bool
      // PrepareForUpgrade is used to prepare a Group for upgrade, like setting status to upgrading
      PrepareForUpgrade() bool
      UpgradeStrategy
      }

      // UpgradeStategy defines strategies for upgrade. Default strategy is delete a node and create an
      // "upgraded" node. The default strategy reduces workload capacity during upgrade. Additive strategy
      // creates a new node and when it is ready, registers new node with the cluster and removes the old
      // node. This gives additional workload capacity during upgrade.
      type UpgradeStrategy interface {
      // Upgrade upgrades a cluster or a group.
      Upgrade() error
      }

      // Ensurer ensures a resource is created and present.
      type Ensurer interface {
      // Ensure ensures a resource.
      Ensure() error
      }

      // Provisioner provisions a Role (master or worker) in the cluster. This is the top level provisioner for
      // a K8S cluster.
      type Provisioner interface {
      Initializer
      // Role returns role name of the provisioner.
      Role() string
      // ProvisionRole provisions a K8S cluster role.
      ProvisionRole() error
      StatusUpdater
      Deleter
      }

      // GroupProvisoner provisions a Group (master group and one or more worker groups).
      type GroupProvisoner interface {
      Initializer
      // ProvisionGroup provisions a Group.
      ProvisionGroup() error
      StatusUpdater
      Deleter
      }

      // NodeProvisioner provisions an individual node using the cloud provider APIs.
      type NodeProvisioner interface {
      Initializer
      Ensurer
      StatusUpdater
      Deleter
      }

      // Node implements NodeProvisioner interface
      type Node struct{}

      // Group implements GroupProvisioner interface
      type Group struct {
      NodeProvisioner NodeProvisioner
      }

      // Master implements Provisioner
      type Master struct {
      Role string
      GroupProvisoner GroupProvisoner
      Upgrader Upgrader
      StatusUpdater StatusUpdater
      }

      func NewMaster() Provisioner {
      // Inject dependencies and return a &Master
      }


      Does this look like a good design? Is it idiomatic Go? Any suggestions are greatly appreciated!










      share|improve this question







      New contributor




      ragas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      I'm fairly new to Go and working on an application to create VMs in a some cloud provider. I'm trying to design interfaces and I'd love some reviews.



      The application creates a cluster (group of VMs with some software installed). The cluster has two roles: master and worker. And in each role, you can have node groups (master can have only one node group and worker role can have N node groups). So a role provisions N groups and a group provisions M nodes, updating status objects after each step. Here's what I've come up with so far (I've removed method parameters to make it easy to read):



      // Initialize is used to initialize objects during a cluster creation. Use this
      // at the given level (Role, Group or Node) to initialize things like status
      // objects specific to that level.
      type Initializer interface {
      // Initialize inits objects in a Cluster type.
      Initialize() error
      }

      // StatusUpdater is used to update status of Group or Node at a given level.
      type StatusUpdater interface {
      // UpdateStatus updates the ClusterStatus object.
      UpdateStatus() error
      }

      // Deleter deletes clusters, node groups and nodes.
      type Deleter interface {
      // RunPreDelete is used to run things before deletion of resources.
      RunPreDelete() error
      // Delete deletes a Role, Group or Node interface.
      Delete()
      // RunPostDelete is used to run things after deletion of resources.
      RunPostDelete() error
      }

      // Upgrade upgrades clusters and node groups.
      type Upgrader interface {
      // Upgradeable is used to determine if the cluster is ready for an upgrade.
      Upgradeable() bool
      // PrepareForUpgrade is used to prepare a Group for upgrade, like setting status to upgrading
      PrepareForUpgrade() bool
      UpgradeStrategy
      }

      // UpgradeStategy defines strategies for upgrade. Default strategy is delete a node and create an
      // "upgraded" node. The default strategy reduces workload capacity during upgrade. Additive strategy
      // creates a new node and when it is ready, registers new node with the cluster and removes the old
      // node. This gives additional workload capacity during upgrade.
      type UpgradeStrategy interface {
      // Upgrade upgrades a cluster or a group.
      Upgrade() error
      }

      // Ensurer ensures a resource is created and present.
      type Ensurer interface {
      // Ensure ensures a resource.
      Ensure() error
      }

      // Provisioner provisions a Role (master or worker) in the cluster. This is the top level provisioner for
      // a K8S cluster.
      type Provisioner interface {
      Initializer
      // Role returns role name of the provisioner.
      Role() string
      // ProvisionRole provisions a K8S cluster role.
      ProvisionRole() error
      StatusUpdater
      Deleter
      }

      // GroupProvisoner provisions a Group (master group and one or more worker groups).
      type GroupProvisoner interface {
      Initializer
      // ProvisionGroup provisions a Group.
      ProvisionGroup() error
      StatusUpdater
      Deleter
      }

      // NodeProvisioner provisions an individual node using the cloud provider APIs.
      type NodeProvisioner interface {
      Initializer
      Ensurer
      StatusUpdater
      Deleter
      }

      // Node implements NodeProvisioner interface
      type Node struct{}

      // Group implements GroupProvisioner interface
      type Group struct {
      NodeProvisioner NodeProvisioner
      }

      // Master implements Provisioner
      type Master struct {
      Role string
      GroupProvisoner GroupProvisoner
      Upgrader Upgrader
      StatusUpdater StatusUpdater
      }

      func NewMaster() Provisioner {
      // Inject dependencies and return a &Master
      }


      Does this look like a good design? Is it idiomatic Go? Any suggestions are greatly appreciated!







      object-oriented design-patterns go






      share|improve this question







      New contributor




      ragas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question







      New contributor




      ragas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question






      New contributor




      ragas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 3 hours ago









      ragasragas

      1




      1




      New contributor




      ragas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      ragas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      ragas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          0






          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });






          ragas is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211502%2fgo-interface-design-for-a-cluster-provisioner-application%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          ragas is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          ragas is a new contributor. Be nice, and check out our Code of Conduct.













          ragas is a new contributor. Be nice, and check out our Code of Conduct.












          ragas is a new contributor. Be nice, and check out our Code of Conduct.
















          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211502%2fgo-interface-design-for-a-cluster-provisioner-application%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          How to make a Squid Proxy server?

          第一次世界大戦

          Touch on Surface Book