Package: github-terraform-import
Github Terraform ImportPython library to allow simple programmatic control of importing a Github organization as terraform resources.The library exposes four key components:Dataclass definitions of all terraform resources in the Github Provider (github_terraform_import.formatter.github_types.*)Formatter to easily convert dataclass types into valid terraform configuration syntax (github_terraform_import.formatter.Formatter)A metaclass required to implement a visitor pattern for all resources (github_terraform_import.visitor.VisitMethodInjector)An interface with the Github REST API that will dynamically load Github resources based on methods defined in the given visitor classgithub_terraform_import.provider.GithubProviderUsageCreate a file for each repository which contains the following repository specific resourcesgithub_repository,github_repository_collaborator,github_team_repository.importosimportsysfromgithub_terraform_import.visitorimportVisitMethodInjectorfromgithub_terraform_import.github_typesimport(GithubRepository,GithubRepositoryCollaborator,GithubTeamRepository,)fromgithub_terraform_import.providerimportGithubProviderfromgithub_terraform_import.formatterimportFormatterclassRepositoryConfigurationGenerator(metaclass=VisitMethodInjector):def__init__(self,path):self._root=pathdefvisit_github_repository(self,repository:GithubRepository):file_=os.path.join(self._root,f"{repository.name}.tf")withopen(file_,"a+")asf:Formatter.format(repository.name,repository,out=f)defvisit_github_repository_collaborator(self,collaborator:GithubRepositoryCollaborator):file_=os.path.join(self._root,f"{collaborator.repository}.tf")withopen(file_,"a+")asf:Formatter.format(collaborator.username,collaborator,out=f)defvisit_github_team_repository(self,team:GithubTeamRepository):file_=os.path.join(self._root,f"{team.repository}.tf")withopen(file_,"a+")asf:Formatter.format(team.team_id,team,out=f)defmain():iflen(sys.argv)<4:print("Usage: example{token}{organization}{output_directory}")exit()directory=sys.argv[3]ifnotos.path.exists(directory):os.makedirs(directory)generator=RepositoryConfigurationGenerator(directory)provider=GithubProvider(sys.argv[1],sys.argv[2])provider.visit(generator)if__name__=="__main__":main()FeaturesWrap around the Github API to provide terraform resourcesTyped resources for each of the terraform resourcesDynamic resource fetching based on declared visitor methodsAutomatic caching of resources on multiple runsFormatting of resource classes to terraform configurationDetectable missing visitor methodsSupported ResourcesResourceSupportedNotesgithub_actions_secret:heavy_check_mark:plaintext_valuevalue cannot be imported from Github API, this must be added manually. Defaults to 'WARNING: Secrets cannot be imported via Github API'github_branchgithub_branch_protection:heavy_check_mark:github_issue_label:heavy_check_mark:github_membership:heavy_check_mark:github_organization_block:heavy_check_mark:github_organization_project:heavy_check_mark:github_organization_webhook:heavy_check_mark:github_project_column:heavy_check_mark:github_repository:heavy_check_mark:delete_branch_on_merge,auto_init,gitignore_template,license_templateare not provided by the APIgithub_repository_collaborator:heavy_check_mark:github_repository_deploy_key:heavy_check_mark:github_repository_filegithub_repository_project:heavy_check_mark:github_repository_webhook:heavy_check_mark:github_team:heavy_check_mark:ldap_dnnot provided by the APIgithub_team_membership:heavy_check_mark:github_team_repository:heavy_check_mark:github_user_gpg_keygithub_user_invitation_acceptergithub_user_ssh_keyVisitMethodInjectorUse theVisitMethodInjectormetaclass in your customised visitor class to provide instructions for handling various fetched resources.Standard UseThe standard use case for your visitor class is to define a method for each of the resources you wish to import. For example if you wish to import all the repository webhooks, a class likeFetchRepositoryWebhookswould suffice.classFetchRepositoryWebhooks(metaclass=VisitMethodInjector):defvisit_github_repository_webhook(self,webhook:GithubRepositoryWebhook):passVisit methods must be named, asvisit_{resource_name}.Default MethodIf there is some method that should be run for every resource without an implemented visitor method, you can use the default method for this purpose.classFetchWithDefault(metaclass=VisitMethodInjector):defvisit_github_repository_webhook(self,webhook:GithubRepositoryWebhook):passdefdefault(self,resource:Resource):print(resource)FetchWithDefaultwill call default for all of the resources exceptgithub_repository_webhook.ValidationIf you want to ensure that every resource has an implemented visitor method, then setting the class variableignore_missingtoFalsewill cause aTypeErrorto be thrown if there are any missing visitor methods.classFetchWithValidation(metaclass=VisitMethodInjector):ignore_missing=FalseFetchWithValidationwill throw a type exception when constructed listing all of the missing visit methods.FormatterTheFormatterclass provides a way of converting the supplied dataclasses for each resource into an appropriately formatted Terraform resource.This is accomplished by calling theFormatter.formatmethod. The method can also be used for any custom dataclasses so long as they inherit fromgithub_terraform_import.github_types.Resource.Any member variables starting with an underscore, conventionally private, are not generated in the resource.@dataclassclassNestedDetails(Block):description:strtopics:List[str]@dataclassclassMyTerraformResource(Resource):name:strid:intvalid:boolfriends:List[str]details:NestedDetailsThe aboveMyTerraformResourceis an example dataclass definition which showcases the various supported types of the formatter.Executing the following will write the resource toout.txtdetails=NestedDetails(description="Things I like",topics=["verification","optimisation"],)resource=MyTerraformResource(name="a special resource",id="special",valid=True,friends=[],details=details,)withopen("out.txt","w")asfile:Formatter.format("my_resource_name",resource,out=file)The contents of out should then be:resource "my_terraform_resource" "my_resource_name" {
    name = "a special resource"
    id = special
    valid = true
    friends = []
    details {
        description = "Things I like"
        topics = [
            "verification"
            "optimisation"
        ]
    }
}If theoutkeyword argument is omitted from theFormatter.formatmethod then the resource will be printed to standard out.