{"action":"created","comment":{"url":"https://api.github.com/repos/giantswarm/azure-operator/pulls/comments/198799936","pull_request_review_id":132792397,"id":198799936,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5ODc5OTkzNg==","diff_hunk":"@@ -9,116 +9,491 @@ import (\n \tproviderv1alpha1 \"github.com/giantswarm/apiextensions/pkg/apis/provider/v1alpha1\"\n \t\"github.com/giantswarm/microerror\"\n \n+\t\"github.com/giantswarm/azure-operator/service/controller/v3/controllercontext\"\n \t\"github.com/giantswarm/azure-operator/service/controller/v3/key\"\n )\n \n+const (\n+\tmasterVersionsKey  = \"masterVersionBundleVersions\"\n+\tversionsKey        = \"versionBundleVersions\"\n+\tvmssDeploymentName = \"cluster-vmss-template\"\n+\tworkerVersionsKey  = \"workerVersionBundleVersions\"\n+)\n+\n func (r *Resource) EnsureCreated(ctx context.Context, obj interface{}) error {\n \tcustomObject, err := key.ToCustomObject(obj)\n \tif err != nil {\n \t\treturn microerror.Mask(err)\n \t}\n-\n-\terr = r.ensureDeploymentUpdate(ctx, customObject, key.MasterVMSSName, key.MasterInstanceName)\n+\tdeploymentsClient, err := r.getDeploymentsClient()\n \tif err != nil {\n \t\treturn microerror.Mask(err)\n \t}\n-\terr = r.ensureDeploymentUpdate(ctx, customObject, key.WorkerVMSSName, key.WorkerInstanceName)\n-\tif err != nil {\n-\t\treturn microerror.Mask(err)\n+\n+\t{\n+\t\tcc, err := controllercontext.FromContext(ctx)\n+\t\tif err != nil {\n+\t\t\treturn microerror.Mask(err)\n+\t\t}\n+\t\terr = cc.Validate()\n+\t\tif err != nil {\n+\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"missing dispatched output values in controller context\")\n+\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"canceling resource for custom object\")\n+\t\t\treturn nil\n+\t\t}\n \t}\n \n-\treturn nil\n-}\n+\t{\n+\t\td, err := deploymentsClient.Get(ctx, key.ClusterID(customObject), vmssDeploymentName)\n+\t\tif IsDeploymentNotFound(err) {\n+\t\t\t// fall through\n+\t\t} else if err != nil {\n+\t\t\treturn microerror.Mask(err)\n+\t\t} else {\n+\t\t\ts := *d.Properties.ProvisioningState\n+\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", fmt.Sprintf(\"deployment is in state '%s'\", s))\n+\n+\t\t\tif !key.IsFinalProvisioningState(s) {\n+\t\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"canceling resource for custom object\")\n+\t\t\t\treturn nil\n+\t\t\t}\n+\t\t}\n+\t}\n \n-func (r *Resource) ensureDeploymentUpdate(ctx context.Context, customObject providerv1alpha1.AzureConfig, deploymentNameFunc func(customObject providerv1alpha1.AzureConfig) string, instanceNameFunc func(customObject providerv1alpha1.AzureConfig, instanceID string) string) error {\n-\t// Find the next instance ID and instance name we want to trigger the update\n-\t// for. Instance names look something like the following example.\n-\t//\n-\t//     0gjpt-worker-000004\n-\t//\n-\t// Instance IDs are simple non negative integers.\n-\t//\n-\t//     4\n-\t//\n-\tvar instanceID string\n-\tvar instanceName string\n+\tvar masterVersionsValue map[string]string\n \t{\n-\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"looking for the next instance to be updated\")\n+\t\td, err := deploymentsClient.Get(ctx, key.ClusterID(customObject), \"master-vmss-deploy\")\n+\t\tif IsDeploymentNotFound(err) {\n+\t\t\t// fall through\n+\t\t} else if err != nil {\n+\t\t\treturn microerror.Mask(err)\n+\t\t} else {\n+\t\t\tp, err := key.ToMap(d.Properties.Parameters)\n+\t\t\tif err != nil {\n+\t\t\t\treturn microerror.Mask(err)\n+\t\t\t}\n+\t\t\tv, ok := p[versionsKey]\n+\t\t\tif !ok {\n+\t\t\t\t// fall through\n+\t\t\t} else {\n+\t\t\t\tm, err := key.ToMap(v)\n+\t\t\t\tif err != nil {\n+\t\t\t\t\treturn microerror.Mask(err)\n+\t\t\t\t}\n+\t\t\t\tv, err := key.ToKeyValue(m)\n+\t\t\t\tif err != nil {\n+\t\t\t\t\treturn microerror.Mask(err)\n+\t\t\t\t}\n+\t\t\t\tmasterVersionsValue, err = key.ToStringMap(v)\n+\t\t\t\tif err != nil {\n+\t\t\t\t\treturn microerror.Mask(err)\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n \n-\t\tc, err := r.getVMsClient()\n-\t\tif err != nil {\n+\tvar workerVersionsValue map[string]string\n+\t{\n+\t\td, err := deploymentsClient.Get(ctx, key.ClusterID(customObject), \"worker-vmss-deploy\")\n+\t\tif IsDeploymentNotFound(err) {\n+\t\t\t// fall through\n+\t\t} else if err != nil {\n \t\t\treturn microerror.Mask(err)\n+\t\t} else {\n+\t\t\tp, err := key.ToMap(d.Properties.Parameters)\n+\t\t\tif err != nil {\n+\t\t\t\treturn microerror.Mask(err)\n+\t\t\t}\n+\t\t\tv, ok := p[versionsKey]\n+\t\t\tif !ok {\n+\t\t\t\t// fall through\n+\t\t\t} else {\n+\t\t\t\tm, err := key.ToMap(v)\n+\t\t\t\tif err != nil {\n+\t\t\t\t\treturn microerror.Mask(err)\n+\t\t\t\t}\n+\t\t\t\tv, err := key.ToKeyValue(m)\n+\t\t\t\tif err != nil {\n+\t\t\t\t\treturn microerror.Mask(err)\n+\t\t\t\t}\n+\t\t\t\tworkerVersionsValue, err = key.ToStringMap(v)\n+\t\t\t\tif err != nil {\n+\t\t\t\t\treturn microerror.Mask(err)\n+\t\t\t\t}\n+\t\t\t}\n \t\t}\n+\t}\n \n-\t\tg := key.ResourceGroupName(customObject)\n-\t\ts := deploymentNameFunc(customObject)\n-\t\tresult, err := c.List(ctx, g, s, \"\", \"\", \"\")\n+\tvar allMasterInstances []compute.VirtualMachineScaleSetVM\n+\tvar reimagedMasterInstance *compute.VirtualMachineScaleSetVM\n+\tvar updatedMasterInstance *compute.VirtualMachineScaleSetVM\n+\t{\n+\t\tallMasterInstances, err = r.allInstances(ctx, customObject, key.MasterVMSSName)\n \t\tif IsScaleSetNotFound(err) {\n-\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"did not find the scale set\")\n-\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"canceling resource for custom object\")\n-\n-\t\t\treturn nil\n+\t\t\t// fall through\n \t\t} else if err != nil {\n \t\t\treturn microerror.Mask(err)\n+\t\t} else {\n+\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"processing master VMSSs\")\n+\n+\t\t\tupdatedMasterInstance, reimagedMasterInstance, err = r.nextInstance(ctx, customObject, allMasterInstances, key.MasterInstanceName, masterVersionsValue)\n+\t\t\tif err != nil {\n+\t\t\t\treturn microerror.Mask(err)\n+\t\t\t}\n+\t\t\terr = r.updateInstance(ctx, customObject, updatedMasterInstance, key.MasterVMSSName, key.MasterInstanceName)\n+\t\t\tif err != nil {\n+\t\t\t\treturn microerror.Mask(err)\n+\t\t\t}\n+\t\t\terr = r.reimageInstance(ctx, customObject, reimagedMasterInstance, key.MasterVMSSName, key.MasterInstanceName)\n+\t\t\tif err != nil {\n+\t\t\t\treturn microerror.Mask(err)\n+\t\t\t}\n+\n+\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"processed master VMSSs\")\n \t\t}\n+\t}\n \n-\t\tfor _, v := range result.Values() {\n-\t\t\tif key.IsFinalProvisioningState(*v.ProvisioningState) {\n-\t\t\t\tcontinue\n+\tvar allWorkerInstances []compute.VirtualMachineScaleSetVM\n+\tvar reimagedWorkerInstance *compute.VirtualMachineScaleSetVM\n+\tvar updatedWorkerInstance *compute.VirtualMachineScaleSetVM\n+\t{\n+\t\tallWorkerInstances, err = r.allInstances(ctx, customObject, key.WorkerVMSSName)\n+\t\tif IsScaleSetNotFound(err) {\n+\t\t\t// fall through\n+\t\t} else if err != nil {\n+\t\t\treturn microerror.Mask(err)\n+\t\t} else {\n+\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"processing worker VMSSs\")\n+\n+\t\t\tupdatedWorkerInstance, reimagedWorkerInstance, err = r.nextInstance(ctx, customObject, allWorkerInstances, key.WorkerInstanceName, workerVersionsValue)\n+\t\t\tif err != nil {\n+\t\t\t\treturn microerror.Mask(err)\n+\t\t\t}\n+\t\t\terr = r.updateInstance(ctx, customObject, updatedWorkerInstance, key.WorkerVMSSName, key.WorkerInstanceName)\n+\t\t\tif err != nil {\n+\t\t\t\treturn microerror.Mask(err)\n+\t\t\t}\n+\t\t\t// In case the master instance is being updated we want to prevent any\n+\t\t\t// other updates on the workers. This is because the update process\n+\t\t\t// involves the draining of the updated node and if the master is being\n+\t\t\t// updated at the same time the guest cluster's Kubernetes API is not\n+\t\t\t// available in order to drain nodes. As consequence we have to reset the\n+\t\t\t// worker instance selected to be reimaged in order to not update its\n+\t\t\t// version information. The next reconciliation loop will catch up here\n+\t\t\t// and instruct the worker instance to be reimaged again.\n+\t\t\tif reimagedMasterInstance == nil {\n+\t\t\t\terr = r.reimageInstance(ctx, customObject, reimagedWorkerInstance, key.WorkerVMSSName, key.WorkerInstanceName)\n+\t\t\t\tif err != nil {\n+\t\t\t\t\treturn microerror.Mask(err)\n+\t\t\t\t}\n+\t\t\t} else if reimagedWorkerInstance != nil {\n+\t\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", fmt.Sprintf(\"not ensuring instance '%s' to be reimaged due to master processing\", key.WorkerInstanceName(customObject, *reimagedWorkerInstance.InstanceID)))\n+\t\t\t\treimagedWorkerInstance = nil\n \t\t\t}\n \n-\t\t\tinstanceName = instanceNameFunc(customObject, *v.InstanceID)\n+\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"processed worker VMSSs\")\n+\t\t}\n+\t}\n \n-\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", fmt.Sprintf(\"instance '%s' is in state '%s'\", instanceName, *v.ProvisioningState))\n-\t\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"canceling resource for custom object\")\n+\t{\n+\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"ensuring deployment\")\n \n-\t\t\treturn nil\n+\t\tmasterVersionsValue, err := updateVersionParameterValue(allMasterInstances, reimagedMasterInstance, key.VersionBundleVersion(customObject), masterVersionsValue)\n+\t\tif err != nil {\n+\t\t\treturn microerror.Mask(err)\n+\t\t}\n+\t\tworkerVersionsValue, err := updateVersionParameterValue(allWorkerInstances, reimagedWorkerInstance, key.VersionBundleVersion(customObject), workerVersionsValue)\n+\t\tif err != nil {\n+\t\t\treturn microerror.Mask(err)\n+\t\t}\n+\t\tparams := map[string]interface{}{\n+\t\t\tmasterVersionsKey: masterVersionsValue,\n+\t\t\tworkerVersionsKey: workerVersionsValue,\n+\t\t}\n+\t\tcomputedDeployment, err := r.newDeployment(ctx, customObject, params)\n+\t\tif err != nil {\n+\t\t\treturn microerror.Mask(err)\n+\t\t}\n+\t\t_, err = deploymentsClient.CreateOrUpdate(ctx, key.ClusterID(customObject), vmssDeploymentName, computedDeployment)\n+\t\tif err != nil {\n+\t\t\treturn microerror.Mask(err)\n \t\t}\n \n-\t\tfor _, v := range result.Values() {\n-\t\t\tif *v.LatestModelApplied {\n-\t\t\t\tcontinue\n-\t\t\t}\n+\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", \"ensured deployment\")\n+\t}\n+\n+\treturn nil\n+}\n+\n+func (r *Resource) allInstances(ctx context.Context, customObject providerv1alpha1.AzureConfig, deploymentNameFunc func(customObject providerv1alpha1.AzureConfig) string) ([]compute.VirtualMachineScaleSetVM, error) {\n+\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", fmt.Sprintf(\"looking for the scale set '%s'\", deploymentNameFunc(customObject)))\n \n-\t\t\tinstanceID = *v.InstanceID\n-\t\t\tinstanceName = instanceNameFunc(customObject, *v.InstanceID)\n+\tc, err := r.getVMsClient()\n+\tif err != nil {\n+\t\treturn nil, microerror.Mask(err)\n+\t}\n+\n+\tg := key.ResourceGroupName(customObject)\n+\ts := deploymentNameFunc(customObject)\n+\tresult, err := c.List(ctx, g, s, \"\", \"\", \"\")\n+\tif IsScaleSetNotFound(err) {\n+\t\tr.logger.LogCtx(ctx, \"level\", \"debug\", \"message\", fmt.Sprintf(\"did not find the scale set '%s'\", deploymentNameFunc(customObject)))\n+\n+\t\treturn nil, microerror.Mask(scaleSetNotFoundError)","path":"service/controller/v3/resource/instance/create.go","position":null,"original_position":276,"commit_id":"68cc9cd024e29136fd86d217c223198b0ffdcd6b","original_commit_id":"9e4fe90869bf9107518153201d4d719692abdf24","user":{"login":"kopiczko","id":4608994,"node_id":"MDQ6VXNlcjQ2MDg5OTQ=","avatar_url":"https://avatars0.githubusercontent.com/u/4608994?v=4","gravatar_id":"","url":"https://api.github.com/users/kopiczko","html_url":"https://github.com/kopiczko","followers_url":"https://api.github.com/users/kopiczko/followers","following_url":"https://api.github.com/users/kopiczko/following{/other_user}","gists_url":"https://api.github.com/users/kopiczko/gists{/gist_id}","starred_url":"https://api.github.com/users/kopiczko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kopiczko/subscriptions","organizations_url":"https://api.github.com/users/kopiczko/orgs","repos_url":"https://api.github.com/users/kopiczko/repos","events_url":"https://api.github.com/users/kopiczko/events{/privacy}","received_events_url":"https://api.github.com/users/kopiczko/received_events","type":"User","site_admin":false},"body":"> We could move the logging away from here and log where the error is matched against but the result stays the same.\r\n\r\nThis doesn't smell at all.","created_at":"2018-06-28T10:56:44Z","updated_at":"2018-06-28T10:56:44Z","html_url":"https://github.com/giantswarm/azure-operator/pull/248#discussion_r198799936","pull_request_url":"https://api.github.com/repos/giantswarm/azure-operator/pulls/248","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/giantswarm/azure-operator/pulls/comments/198799936"},"html":{"href":"https://github.com/giantswarm/azure-operator/pull/248#discussion_r198799936"},"pull_request":{"href":"https://api.github.com/repos/giantswarm/azure-operator/pulls/248"}},"in_reply_to_id":198783914},"pull_request":{"url":"https://api.github.com/repos/giantswarm/azure-operator/pulls/248","id":195589403,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk1NTg5NDAz","html_url":"https://github.com/giantswarm/azure-operator/pull/248","diff_url":"https://github.com/giantswarm/azure-operator/pull/248.diff","patch_url":"https://github.com/giantswarm/azure-operator/pull/248.patch","issue_url":"https://api.github.com/repos/giantswarm/azure-operator/issues/248","number":248,"state":"open","locked":false,"title":"manages updating and reimaging of instances","user":{"login":"xh3b4sd","id":552769,"node_id":"MDQ6VXNlcjU1Mjc2OQ==","avatar_url":"https://avatars3.githubusercontent.com/u/552769?v=4","gravatar_id":"","url":"https://api.github.com/users/xh3b4sd","html_url":"https://github.com/xh3b4sd","followers_url":"https://api.github.com/users/xh3b4sd/followers","following_url":"https://api.github.com/users/xh3b4sd/following{/other_user}","gists_url":"https://api.github.com/users/xh3b4sd/gists{/gist_id}","starred_url":"https://api.github.com/users/xh3b4sd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xh3b4sd/subscriptions","organizations_url":"https://api.github.com/users/xh3b4sd/orgs","repos_url":"https://api.github.com/users/xh3b4sd/repos","events_url":"https://api.github.com/users/xh3b4sd/events{/privacy}","received_events_url":"https://api.github.com/users/xh3b4sd/received_events","type":"User","site_admin":false},"body":"Towards https://github.com/giantswarm/giantswarm/issues/3272.","created_at":"2018-06-18T17:02:42Z","updated_at":"2018-06-28T10:56:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dd2bc31b9fef2923161dfd82f3151d6802f61053","assignee":{"login":"xh3b4sd","id":552769,"node_id":"MDQ6VXNlcjU1Mjc2OQ==","avatar_url":"https://avatars3.githubusercontent.com/u/552769?v=4","gravatar_id":"","url":"https://api.github.com/users/xh3b4sd","html_url":"https://github.com/xh3b4sd","followers_url":"https://api.github.com/users/xh3b4sd/followers","following_url":"https://api.github.com/users/xh3b4sd/following{/other_user}","gists_url":"https://api.github.com/users/xh3b4sd/gists{/gist_id}","starred_url":"https://api.github.com/users/xh3b4sd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xh3b4sd/subscriptions","organizations_url":"https://api.github.com/users/xh3b4sd/orgs","repos_url":"https://api.github.com/users/xh3b4sd/repos","events_url":"https://api.github.com/users/xh3b4sd/events{/privacy}","received_events_url":"https://api.github.com/users/xh3b4sd/received_events","type":"User","site_admin":false},"assignees":[{"login":"xh3b4sd","id":552769,"node_id":"MDQ6VXNlcjU1Mjc2OQ==","avatar_url":"https://avatars3.githubusercontent.com/u/552769?v=4","gravatar_id":"","url":"https://api.github.com/users/xh3b4sd","html_url":"https://github.com/xh3b4sd","followers_url":"https://api.github.com/users/xh3b4sd/followers","following_url":"https://api.github.com/users/xh3b4sd/following{/other_user}","gists_url":"https://api.github.com/users/xh3b4sd/gists{/gist_id}","starred_url":"https://api.github.com/users/xh3b4sd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xh3b4sd/subscriptions","organizations_url":"https://api.github.com/users/xh3b4sd/orgs","repos_url":"https://api.github.com/users/xh3b4sd/repos","events_url":"https://api.github.com/users/xh3b4sd/events{/privacy}","received_events_url":"https://api.github.com/users/xh3b4sd/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/giantswarm/azure-operator/pulls/248/commits","review_comments_url":"https://api.github.com/repos/giantswarm/azure-operator/pulls/248/comments","review_comment_url":"https://api.github.com/repos/giantswarm/azure-operator/pulls/comments{/number}","comments_url":"https://api.github.com/repos/giantswarm/azure-operator/issues/248/comments","statuses_url":"https://api.github.com/repos/giantswarm/azure-operator/statuses/68cc9cd024e29136fd86d217c223198b0ffdcd6b","head":{"label":"giantswarm:tags","ref":"tags","sha":"68cc9cd024e29136fd86d217c223198b0ffdcd6b","user":{"login":"giantswarm","id":7556340,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc1NTYzNDA=","avatar_url":"https://avatars3.githubusercontent.com/u/7556340?v=4","gravatar_id":"","url":"https://api.github.com/users/giantswarm","html_url":"https://github.com/giantswarm","followers_url":"https://api.github.com/users/giantswarm/followers","following_url":"https://api.github.com/users/giantswarm/following{/other_user}","gists_url":"https://api.github.com/users/giantswarm/gists{/gist_id}","starred_url":"https://api.github.com/users/giantswarm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/giantswarm/subscriptions","organizations_url":"https://api.github.com/users/giantswarm/orgs","repos_url":"https://api.github.com/users/giantswarm/repos","events_url":"https://api.github.com/users/giantswarm/events{/privacy}","received_events_url":"https://api.github.com/users/giantswarm/received_events","type":"Organization","site_admin":false},"repo":{"id":99101543,"node_id":"MDEwOlJlcG9zaXRvcnk5OTEwMTU0Mw==","name":"azure-operator","full_name":"giantswarm/azure-operator","owner":{"login":"giantswarm","id":7556340,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc1NTYzNDA=","avatar_url":"https://avatars3.githubusercontent.com/u/7556340?v=4","gravatar_id":"","url":"https://api.github.com/users/giantswarm","html_url":"https://github.com/giantswarm","followers_url":"https://api.github.com/users/giantswarm/followers","following_url":"https://api.github.com/users/giantswarm/following{/other_user}","gists_url":"https://api.github.com/users/giantswarm/gists{/gist_id}","starred_url":"https://api.github.com/users/giantswarm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/giantswarm/subscriptions","organizations_url":"https://api.github.com/users/giantswarm/orgs","repos_url":"https://api.github.com/users/giantswarm/repos","events_url":"https://api.github.com/users/giantswarm/events{/privacy}","received_events_url":"https://api.github.com/users/giantswarm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/giantswarm/azure-operator","description":"Azure operator manages Kubernetes clusters running in Giantnetes on Azure","fork":false,"url":"https://api.github.com/repos/giantswarm/azure-operator","forks_url":"https://api.github.com/repos/giantswarm/azure-operator/forks","keys_url":"https://api.github.com/repos/giantswarm/azure-operator/keys{/key_id}","collaborators_url":"https://api.github.com/repos/giantswarm/azure-operator/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/giantswarm/azure-operator/teams","hooks_url":"https://api.github.com/repos/giantswarm/azure-operator/hooks","issue_events_url":"https://api.github.com/repos/giantswarm/azure-operator/issues/events{/number}","events_url":"https://api.github.com/repos/giantswarm/azure-operator/events","assignees_url":"https://api.github.com/repos/giantswarm/azure-operator/assignees{/user}","branches_url":"https://api.github.com/repos/giantswarm/azure-operator/branches{/branch}","tags_url":"https://api.github.com/repos/giantswarm/azure-operator/tags","blobs_url":"https://api.github.com/repos/giantswarm/azure-operator/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/giantswarm/azure-operator/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/giantswarm/azure-operator/git/refs{/sha}","trees_url":"https://api.github.com/repos/giantswarm/azure-operator/git/trees{/sha}","statuses_url":"https://api.github.com/repos/giantswarm/azure-operator/statuses/{sha}","languages_url":"https://api.github.com/repos/giantswarm/azure-operator/languages","stargazers_url":"https://api.github.com/repos/giantswarm/azure-operator/stargazers","contributors_url":"https://api.github.com/repos/giantswarm/azure-operator/contributors","subscribers_url":"https://api.github.com/repos/giantswarm/azure-operator/subscribers","subscription_url":"https://api.github.com/repos/giantswarm/azure-operator/subscription","commits_url":"https://api.github.com/repos/giantswarm/azure-operator/commits{/sha}","git_commits_url":"https://api.github.com/repos/giantswarm/azure-operator/git/commits{/sha}","comments_url":"https://api.github.com/repos/giantswarm/azure-operator/comments{/number}","issue_comment_url":"https://api.github.com/repos/giantswarm/azure-operator/issues/comments{/number}","contents_url":"https://api.github.com/repos/giantswarm/azure-operator/contents/{+path}","compare_url":"https://api.github.com/repos/giantswarm/azure-operator/compare/{base}...{head}","merges_url":"https://api.github.com/repos/giantswarm/azure-operator/merges","archive_url":"https://api.github.com/repos/giantswarm/azure-operator/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/giantswarm/azure-operator/downloads","issues_url":"https://api.github.com/repos/giantswarm/azure-operator/issues{/number}","pulls_url":"https://api.github.com/repos/giantswarm/azure-operator/pulls{/number}","milestones_url":"https://api.github.com/repos/giantswarm/azure-operator/milestones{/number}","notifications_url":"https://api.github.com/repos/giantswarm/azure-operator/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/giantswarm/azure-operator/labels{/name}","releases_url":"https://api.github.com/repos/giantswarm/azure-operator/releases{/id}","deployments_url":"https://api.github.com/repos/giantswarm/azure-operator/deployments","created_at":"2017-08-02T10:00:21Z","updated_at":"2018-06-28T08:06:11Z","pushed_at":"2018-06-28T10:42:27Z","git_url":"git://github.com/giantswarm/azure-operator.git","ssh_url":"git@github.com:giantswarm/azure-operator.git","clone_url":"https://github.com/giantswarm/azure-operator.git","svn_url":"https://github.com/giantswarm/azure-operator","homepage":"","size":46499,"stargazers_count":10,"watchers_count":10,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"archived":false,"open_issues_count":12,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":4,"open_issues":12,"watchers":10,"default_branch":"master"}},"base":{"label":"giantswarm:master","ref":"master","sha":"922f9bf4c70165b90065a11b9833e84056b28930","user":{"login":"giantswarm","id":7556340,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc1NTYzNDA=","avatar_url":"https://avatars3.githubusercontent.com/u/7556340?v=4","gravatar_id":"","url":"https://api.github.com/users/giantswarm","html_url":"https://github.com/giantswarm","followers_url":"https://api.github.com/users/giantswarm/followers","following_url":"https://api.github.com/users/giantswarm/following{/other_user}","gists_url":"https://api.github.com/users/giantswarm/gists{/gist_id}","starred_url":"https://api.github.com/users/giantswarm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/giantswarm/subscriptions","organizations_url":"https://api.github.com/users/giantswarm/orgs","repos_url":"https://api.github.com/users/giantswarm/repos","events_url":"https://api.github.com/users/giantswarm/events{/privacy}","received_events_url":"https://api.github.com/users/giantswarm/received_events","type":"Organization","site_admin":false},"repo":{"id":99101543,"node_id":"MDEwOlJlcG9zaXRvcnk5OTEwMTU0Mw==","name":"azure-operator","full_name":"giantswarm/azure-operator","owner":{"login":"giantswarm","id":7556340,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc1NTYzNDA=","avatar_url":"https://avatars3.githubusercontent.com/u/7556340?v=4","gravatar_id":"","url":"https://api.github.com/users/giantswarm","html_url":"https://github.com/giantswarm","followers_url":"https://api.github.com/users/giantswarm/followers","following_url":"https://api.github.com/users/giantswarm/following{/other_user}","gists_url":"https://api.github.com/users/giantswarm/gists{/gist_id}","starred_url":"https://api.github.com/users/giantswarm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/giantswarm/subscriptions","organizations_url":"https://api.github.com/users/giantswarm/orgs","repos_url":"https://api.github.com/users/giantswarm/repos","events_url":"https://api.github.com/users/giantswarm/events{/privacy}","received_events_url":"https://api.github.com/users/giantswarm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/giantswarm/azure-operator","description":"Azure operator manages Kubernetes clusters running in Giantnetes on Azure","fork":false,"url":"https://api.github.com/repos/giantswarm/azure-operator","forks_url":"https://api.github.com/repos/giantswarm/azure-operator/forks","keys_url":"https://api.github.com/repos/giantswarm/azure-operator/keys{/key_id}","collaborators_url":"https://api.github.com/repos/giantswarm/azure-operator/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/giantswarm/azure-operator/teams","hooks_url":"https://api.github.com/repos/giantswarm/azure-operator/hooks","issue_events_url":"https://api.github.com/repos/giantswarm/azure-operator/issues/events{/number}","events_url":"https://api.github.com/repos/giantswarm/azure-operator/events","assignees_url":"https://api.github.com/repos/giantswarm/azure-operator/assignees{/user}","branches_url":"https://api.github.com/repos/giantswarm/azure-operator/branches{/branch}","tags_url":"https://api.github.com/repos/giantswarm/azure-operator/tags","blobs_url":"https://api.github.com/repos/giantswarm/azure-operator/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/giantswarm/azure-operator/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/giantswarm/azure-operator/git/refs{/sha}","trees_url":"https://api.github.com/repos/giantswarm/azure-operator/git/trees{/sha}","statuses_url":"https://api.github.com/repos/giantswarm/azure-operator/statuses/{sha}","languages_url":"https://api.github.com/repos/giantswarm/azure-operator/languages","stargazers_url":"https://api.github.com/repos/giantswarm/azure-operator/stargazers","contributors_url":"https://api.github.com/repos/giantswarm/azure-operator/contributors","subscribers_url":"https://api.github.com/repos/giantswarm/azure-operator/subscribers","subscription_url":"https://api.github.com/repos/giantswarm/azure-operator/subscription","commits_url":"https://api.github.com/repos/giantswarm/azure-operator/commits{/sha}","git_commits_url":"https://api.github.com/repos/giantswarm/azure-operator/git/commits{/sha}","comments_url":"https://api.github.com/repos/giantswarm/azure-operator/comments{/number}","issue_comment_url":"https://api.github.com/repos/giantswarm/azure-operator/issues/comments{/number}","contents_url":"https://api.github.com/repos/giantswarm/azure-operator/contents/{+path}","compare_url":"https://api.github.com/repos/giantswarm/azure-operator/compare/{base}...{head}","merges_url":"https://api.github.com/repos/giantswarm/azure-operator/merges","archive_url":"https://api.github.com/repos/giantswarm/azure-operator/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/giantswarm/azure-operator/downloads","issues_url":"https://api.github.com/repos/giantswarm/azure-operator/issues{/number}","pulls_url":"https://api.github.com/repos/giantswarm/azure-operator/pulls{/number}","milestones_url":"https://api.github.com/repos/giantswarm/azure-operator/milestones{/number}","notifications_url":"https://api.github.com/repos/giantswarm/azure-operator/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/giantswarm/azure-operator/labels{/name}","releases_url":"https://api.github.com/repos/giantswarm/azure-operator/releases{/id}","deployments_url":"https://api.github.com/repos/giantswarm/azure-operator/deployments","created_at":"2017-08-02T10:00:21Z","updated_at":"2018-06-28T08:06:11Z","pushed_at":"2018-06-28T10:42:27Z","git_url":"git://github.com/giantswarm/azure-operator.git","ssh_url":"git@github.com:giantswarm/azure-operator.git","clone_url":"https://github.com/giantswarm/azure-operator.git","svn_url":"https://github.com/giantswarm/azure-operator","homepage":"","size":46499,"stargazers_count":10,"watchers_count":10,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"archived":false,"open_issues_count":12,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":4,"open_issues":12,"watchers":10,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/giantswarm/azure-operator/pulls/248"},"html":{"href":"https://github.com/giantswarm/azure-operator/pull/248"},"issue":{"href":"https://api.github.com/repos/giantswarm/azure-operator/issues/248"},"comments":{"href":"https://api.github.com/repos/giantswarm/azure-operator/issues/248/comments"},"review_comments":{"href":"https://api.github.com/repos/giantswarm/azure-operator/pulls/248/comments"},"review_comment":{"href":"https://api.github.com/repos/giantswarm/azure-operator/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/giantswarm/azure-operator/pulls/248/commits"},"statuses":{"href":"https://api.github.com/repos/giantswarm/azure-operator/statuses/68cc9cd024e29136fd86d217c223198b0ffdcd6b"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"kopiczko"}}